Comment générer un patch git pour un commit spécifique?

1233

J'ai besoin d'écrire un script qui crée des correctifs pour une liste de numéros de validation SHA1.

J'ai essayé d'utiliser git format-patch <the SHA1>, mais cela a généré un patch pour chaque commit depuis ce SHA1. Après que quelques centaines de correctifs aient été générés, j'ai dû arrêter le processus.

Existe-t-il un moyen de générer un patch uniquement pour le SHA1 spécifique?

elle
la source

Réponses:

1991

Essayer:

git format-patch -1 <sha>

ou

git format-patch -1 HEAD

Selon le lien de documentation ci-dessus, l' -1indicateur indique à git combien de validations doivent être incluses dans le patch;

- <n>

     Préparez les correctifs à partir des validations les plus élevées.


Appliquez le patch avec la commande:

git am < file.patch
manojlds
la source
211
Application du patch: git apply --stat file.patch# afficher les statistiques. git apply --check file.patch# vérifier l'erreur avant de postuler. git am < file.patch# appliquer enfin le patch.
Adrian
3
Cela ne semble pas fonctionner si le dernier commit est une fusion d'une autre branche.
Lex Li
2
Pour appliquer le correctif sur les fichiers à l'aide des fins de ligne CRLF:git am --keep-cr < mypatch.patch
Michael Schmeißer
40
Utilisez git am -3 < file.patchpour appliquer en utilisant une fusion à trois voies qui vous permettra de résoudre les conflits en utilisant git mergetoolensuite (ou en modifiant manuellement) trouvé ici .
Matt
6
Cette commande ne fonctionne également que pour un ou des fichiers spécifiques de la validation: git format-patch -1 <sha> path/to/file.jscela créera un patch contenant uniquement les différences pour le fichier.js
Kristóf Dombi
281

Pour générer les correctifs à partir des validations les plus élevées à partir d'un hachage sha1 spécifique:

git format-patch -<n> <SHA1>

Les 10 derniers patchs de head dans un seul fichier de patch:

git format-patch -10 HEAD --stdout > 0001-last-10-commits.patch
Sriram Murali
la source
2
pouvez-vous s'il vous plaît avoir la gentillesse de fournir un exemple pour la première commande
Kasun Siyambalapitiya
1
git format-patch -1 HEADgénérera un patch pour le commit le plus récent
Sriram Murali
1
pardonnez-moi de le demander, alors quand c'est le cas, -2il génère des correctifs pour les 2 derniers commits, et une autre chose à clarifier est que la commande got format-patch -2 HEADest la même que la lignegit format-patch HEAD~2
Kasun Siyambalapitiya
85

Supposons que vous ayez validé l'ID 2 après la validation 1, vous pourriez exécuter:

git diff 2 1 > mypatch.diff

où 2 et 1 sont des hachages SHA.

brandon
la source
Merci dookehster pour la réponse. Cela signifie que j'ai besoin du script pour trouver les commits qui ont précédé ceux qui m'intéressent. J'espérais pouvoir éviter cela.
elle
11
@elle, non, tu n'as pas - git diff hash^ hash. le "hash ^" donne le commit précédé. (mais, bien sûr, la réponse de manojlds est meilleure)
J-16 SDiZ
2
git show HEAD > mypatch.diffpendant que vous êtes sur le commit devrait faire de même.
andho
1
@dookehester est-il correct ou est-ce l'inverse,git diff 1 2
Kasun Siyambalapitiya
1
Cela n'inclura aucun fichier binaire dans le diff.
stuckj
55

Cette commande (comme déjà suggéré par @ Naftuli Tzvi Kay ):

git format-patch -1 HEAD

Remplacez HEADpar un hachage ou une plage spécifique.

générera le fichier de correctif pour le dernier commit formaté pour ressembler au format de boîte aux lettres UNIX.

-<n> - Préparez les correctifs à partir des validations les plus élevées.

Vous pouvez ensuite réappliquer le fichier correctif dans un format de boîte aux lettres en:

git am -3k 001*.patch

Voir: man git-format-patch.

kenorb
la source
Merci! Je pense qu'il vaut la peine de noter que l'application du patch créera un commit avec un message de commit préfixé par [PATCH]. C'est facile à réparer cependant
Mike S
2
Phénoménal. OP, vous ne l'avez pas accepté parce que ...? @MikeS Non, pas plus que tout autre gitpatch formaté, du moins si l'utilisateur l'applique correctement.
underscore_d
2
@MikeS Je n'ai pas vraiment cherché pourquoi, mais en laissant de côté le -kflag ( git am -3) a corrigé ce formulaire moi (pas de PATCH[0/10]messages de commit). Git version 2.20.1.windows.1
jannis
31
git format-patch commit_Id~1..commit_Id  
git apply patch-file-name

Solution simple et rapide.

zdrsoft
la source
5
N'oubliez pas non plus d'appeler git apply --check patch-file-nameavant d'appliquer un patch. Cela vous évitera des problèmes.
iamantony
16

Si vous voulez être sûr que le patch (commit unique) sera appliqué au dessus d'un commit spécifique, vous pouvez utiliser la nouvelle option git 2.9 (juin 2016) git format-patch --base

git format-patch --base=COMMIT_VALUE~ -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git format-patch --base=auto -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git config format.useAutoBase true
git format-patch -M -C COMMIT_VALUE~..COMMIT_VALUE

Voir commit bb52995 , commit 3de6651 , commit fa2ab86 , commit ded2c09 (26 avril 2016) par Xiaolong Ye (``) .
(Fusionné par Junio ​​C Hamano - gitster- en commit 72ce3ff , 23 mai 2016)

format-patch: ajouter l' --baseoption ' ' pour enregistrer les informations de l'arborescence de base

Les responsables de maintenance ou les testeurs tiers peuvent vouloir connaître l'arborescence de base exacte à laquelle s'applique la série de correctifs. Apprenez à git format-patch a '--base option ' pour enregistrer les informations de l'arborescence de base et ajoutez-les à la fin du premier message (soit la lettre de motivation, soit le premier patch de la série).

L'information de l'arborescence de base se compose de la «validation de base», qui est une validation bien connue qui fait partie de la partie stable de l'historique du projet, sur laquelle tout le monde travaille, et de zéro ou plusieurs «correctifs prérequis», qui sont bien connus les correctifs en vol qui ne font pas encore partie de la «validation de base» qui doivent être appliqués au-dessus de la «validation de base» dans l'ordre topologique avant que les correctifs puissent être appliqués.

Le "commit de base" est représenté par " base-commit:" suivi du 40-hex du nom de l'objet commit.
Un "patch prérequis" est indiqué par " prerequisite-patch-id:" suivi du "patch id" de 40 hex, qui peut être obtenu en passant le patch via la git patch-id --stablecommande " ".


Git 2.23 (Q3 2019) améliorera cela, car " --base" l'option de " format-patch" a calculé les patch-idscorrectifs prérequis pour de manière instable, qui a été mis à jour pour calculer d'une manière compatible avec " git patch-id --stable".

Voir commit a8f6855 , commit 6f93d26 (26 avril 2019) par Stephen Boyd ( akshayka) .
(Fusionné par Junio ​​C Hamano - gitster- dans commit 8202d12 , 13 juin 2019)

format-patch: rendre la --base patch-idsortie stable

Nous ne vidions pas le contexte à chaque fois que nous traitions un morceau dans le patch-idcode de génération diff.c, mais nous le faisions lorsque nous générions des identifiants de correctifs "stables" avec l' patch-idoutil ' '.

Port de laisser cette même logique au- dessus de patch-id.cen diff.csorte que nous pouvons obtenir le même hachage quand nous générons patch pour ids « format-patch --base=» types d'invocations de commande.


Avant Git 2.24 (Q4 2019), " git format-patch -o <outdir>" faisait l'équivalent de " mkdir <outdir>" pas " mkdir -p <outdir>", qui est en cours de correction.

Voir commit edefc31 (11 octobre 2019) par Bert Wesarg ( bertwesarg) .
(Fusionné par Junio ​​C Hamano - gitster- en commit f1afbb0 , 18 oct.2019 )

format-patch: créer les principaux composants du répertoire de sortie

Signé par: Bert Wesarg

'git format-patch -o' a fait un équivalent de 'mkdir' et non de 'mkdir -p', qui est en cours de correction.

Évitez l'utilisation de " adjust_shared_perm" sur les principaux répertoires, ce qui peut avoir des conséquences sur la sécurité. Atteint en désactivant temporairement les ' config.sharedRepository' comme ' git init'.


Avec Git 2.25 (T1 2020), " git rebase" ne fonctionnait pas bien lorsque la format.useAutoBasevariable de configuration est définie, ce qui a été corrigé.

Voir commit cae0bc0 , commit 945dc55 , commit 700e006 , commit a749d01 , commit 0c47e06 (04 décembre 2019) par Denton Liu ( Denton-L) .
(Fusionné par Junio ​​C Hamano - gitster- en commit 71a7de7 , 16 )

rebase: réparer la format.useAutoBaserupture

Rapporté par: Christian Biesinger
Signé par: Denton Liu

Avec format.useAutoBase = true , l'exécution de rebase a entraîné une erreur:

fatal: failed to get upstream, if you want to record base commit automatically,
please use git branch --set-upstream-to to track a remote branch.
Or you could specify base commit by --base=<base-commit-id> manually
error:
git encountered an error while preparing the patches to replay
these revisions:

ede2467cdedc63784887b587a61c36b7850ebfac..d8f581194799ae29bf5fa72a98cbae98a1198b12

As a result, git cannot rebase them.

Corrigez cela en passant toujours --no-baseau format-patch de rebase afin que l'effet de format.useAutoBasesoit annulé.

VonC
la source
8

Pour générer le chemin à partir d'une validation spécifique (pas la dernière validation):

git format-patch -M -C COMMIT_VALUE~1..COMMIT_VALUE
Makah
la source
5

si vous voulez juste différencier le fichier spécifié, vous pouvez:

git diff master 766eceb - connexions /> 000-mysql-connector.patch

jiahut
la source
0

Avec mes antécédents mercuriels j'allais utiliser:

git log --patch -1 $ID > $file

Mais j'envisage d'utiliser git format-patch -1 $IDmaintenant.

alls0rts
la source
-5

Comment générer un patch uniquement pour le SHA1 spécifique?

C'est assez simple:

Option 1. git show commitID > myFile.patch

Option 2. git commitID~1..commitID > myFile.patch

Remarque: remplacez commitIDpar l'ID de validation réel (code de validation SHA1).

Ankush
la source
3
L'option 1 est carrément fausse et n'a aucun rapport avec la question.
Anshuman Manral
3
L'option 2 est également une commande non valide. Vous obtiendrez une erreur comme: git a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 ~ 1..a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 git: 'a5f4bcaeb7fa7de27ae79d9522332e872889bbf0bb288b Voir 'git --help'. Veuillez vérifier avant de poster des réponses
Anshuman Manral