erreur git am: «le patch ne s’applique pas»

J’essaie de déplacer plusieurs commits d’un projet vers un autre, similaire, en utilisant git.

J’ai donc créé un patch contenant 5 commits:

git format-patch 4af51 --stdout > changes.patch 

Ensuite, déplacez le correctif dans le dossier du deuxième projet et souhaitez appliquer le correctif:

 git am changes.patch 

… mais cela me donne une erreur:

 Applying: Fixed products ordering in order summary. error: patch failed: index.php:17 error: index.php: patch does not apply Patch failed at 0001 Fixed products ordering in order summary. The copy of the patch that failed is found in: c:/.../project2/.git/rebase-apply/patch When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". 

J’ai donc ouvert le fichier index.php, mais rien n’y a changé. Je suppose que certains >>>>>>> points, etc., comme lors de la résolution des conflits de fusion, mais aucun conflit n’a été marqué dans le fichier. git status m’a également donné une liste vide de fichiers modifiés (seuls les changements.patch était là). Donc je lance git am --continue , mais une autre erreur apparaît:

 Applying: Fixed products ordering in order summary. No changes - did you forget to use 'git add'? If there is nothing left to stage, chances are that something else already introduced the same changes; you might want to skip this patch. When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". 

J’utilise Windows 7 et la dernière version de git “1.9.4.msysgit.1”

PS Après quelques heures de recherche sur Google, j’ai trouvé peu de solutions, mais rien ne fonctionne pour moi:


 git am -3 changes.patch 

donne une erreur “sha1 information”:

 Applying: Fixed products ordering in order summary. fatal: sha1 information is lacking or useless (index.php). Repository lacks necessary blobs to fall back on 3-way merge. Cannot fall back to three-way merge. Patch failed at 0001 Fixed products ordering in order summary. The copy of the patch that failed is found in: c:/.../project2/.git/rebase-apply/patch When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". 

 git am changes.patch --ignore-whitespace --no-scissors --ignore-space-change 

donne la première erreur comme ci-dessus: “erreur: patch a échoué: index.php: 17”, mais aucune marque de conflit dans index.php n’a été ajoutée.

Qu’est-ce qu’un patch?

Un patch est un peu plus (voir ci-dessous) qu’une série d’instructions: «ajoutez ceci ici», «supprimez-le», «changez cette troisième chose en quasortingème». C’est pourquoi git vous dit:

 The copy of the patch that failed is found in: c:/.../project2/.git/rebase-apply/patch 

Vous pouvez ouvrir ce patch dans votre visualiseur ou éditeur favori, ouvrir les fichiers à modifier dans votre éditeur préféré et “appliquer manuellement le patch en utilisant ce que vous savez (et ce que ne fait pas git) pour déterminer comment ” append this here “doit être fait lorsque les fichiers à modifier ne ressemblent plus à ce qu’ils ont fait lorsqu’ils ont été modifiés auparavant, avec ces modifications qui vous ont été apscopes en tant que patch.

Un peu plus

Une fusion à trois voies introduit cette information “un peu plus” que la simple “série d’instructions”: elle vous indique également la version originale du fichier. Si votre référentiel a la version originale, votre git peut comparer ce que vous avez fait à un fichier, à ce que le correctif dit de faire avec le fichier.

Comme vous l’avez vu ci-dessus, si vous demandez la fusion à trois, git ne peut pas trouver la “version originale” dans l’autre référentiel, elle ne peut donc même pas tenter la fusion à trois. En conséquence, vous n’obtenez aucun marqueur de conflit et vous devez effectuer l’application de patch à la main.

Utiliser --reject

Lorsque vous devez appliquer le correctif à la main, il est toujours possible que git applique automatiquement la plupart des correctifs et ne laisse à l’entité que quelques morceaux capables de raisonner sur le code (ou tout ce qui nécessite un correctif). . L’ajout de --reject indique à git de le faire et laisse les parties “inapplicables” du patch dans les fichiers de rejet. Si vous utilisez cette option, vous devez toujours appliquer manuellement chaque patch défaillant et déterminer ce qu’il convient de faire avec les parties rejetées.

Une fois que vous avez apporté les modifications requirejses, vous pouvez git add les fichiers modifiés et utiliser git am --continue à dire à git de valider les modifications et de passer au patch suivant.

Et s’il n’y a rien à faire?

Comme nous n’avons pas votre code, je ne peux pas dire si c’est le cas, mais parfois, vous vous retrouvez avec l’un des correctifs indiquant des choses équivalant, par exemple, à «corriger l’orthographe d’un mot sur la ligne 42». quand l’orthographe y était déjà fixée.

Dans ce cas particulier, après avoir regardé le patch et le code actuel, vous devriez vous dire: “aha, ce patch ne doit être ignoré que complètement!” C’est à ce moment que vous utilisez les autres conseils que git a déjà imprimés:

 If you prefer to skip this patch, run "git am --skip" instead. 

Si vous lancez git am --skip , git va ignorer ce correctif, de sorte que s’il y avait cinq correctifs dans la boîte aux lettres, il ne contiendrait que quatre commits, au lieu de cinq (ou trois au lieu de cinq). etc).

git format-patch aussi le drapeau -B .

La description dans la page de manuel laisse beaucoup à désirer, mais dans un langage simple, c’est le seuil que le format-patch va respecter avant de réécrire complètement le fichier (par une simple suppression de tout ce qui est suivi d’une seule insertion de tout nouveau).

Cela m’a été très utile lorsque l’édition manuelle était trop lourde et que la source faisait plus autorité que ma destination.

Un exemple:

 git format-patch -B10% --stdout my_tag_name > big_patch.patch git am -3 -i < big_patch.patch 

J’ai eu cette erreur, j’ai pu le surmonter en utilisant: patch -p1 < example.patch

Je l'ai pris ici: https://www.drupal.org/node/1129120