web-dev-qa-db-fra.com

git add --interactive "Votre morceau modifié ne s'applique pas"

J'essaie d'utiliser git add --interactive pour ajouter sélectivement des modifications à mon index, mais je reçois continuellement le message "Votre morceau modifié ne s'applique pas. Modifiez à nouveau ..." Je reçois ce message même si je choisis l'option e et je sauvegarde/ferme immédiatement mon éditeur. En d'autres termes, sans éditer le morceau, le patch ne s'applique pas.

Voici l'exemple exact que j'utilise (j'essaie de créer une petite démo):

Fichier original:

first change
second change off branch
third change off branch
second change
third change
fourth change

Nouveau fichier:

Change supporting feature 1
first change
second change off branch
third change off branch
second change
third change
fourth change
bug fix 1
change supporting feature 1

J'essaie de montrer comment utiliser git add --interactive pour ajouter uniquement la ligne "correctif 1" à l'index. En cours d'exécution interactive ajouter sur le fichier, je choisis le mode patch. Il me présente 

diff --git a/newfile b/newfile
index 6d501a3..8b81ae9 100644
--- a/newfile
+++ b/newfile
@@ -1,6 +1,9 @@
+Change supporting feature 1
 first change
 second change off branch
 third change off branch
 second change
 third change
 fourth change
+bug fix 1
+change supporting feature 1

Je réponds avec split, suivi de "non" pour appliquer le premier morceau. Le deuxième morceau, je tente d’éditer. Au départ, j'ai essayé de supprimer le résultat final - cela n'a pas fonctionné. Laisser le morceau seul complètement ne fonctionne pas non plus, et je ne comprends pas pourquoi.

74
Josh

Pour cet exemple particulier, vous devez modifier les numéros de ligne dans le morceau. Changer la ligne:

 @@ -1,6 +2,8 @@ 

de sorte qu'il se lise à la place:

 @@ -2,7 +2,8 @@ 
36
William Pursell

Est-ce que c'est comme dans ce post git-add ?

Éditer manuellement le morceau est extrêmement puissant, mais aussi un peu compliqué si vous ne l'avez jamais fait auparavant.
La chose la plus importante à garder à l’esprit: le diff est toujours mis en retrait avec un caractère en plus de l’indentation qui existe.
Le personnage peut être soit:

  • un espace (indique une ligne inchangée), 
  • un - indiquant que la ligne a été supprimée, 
  • ou un + indiquant que la ligne a été ajoutée. 

Rien d'autre. Ce doit être soit un espace, un - ou un +. Tout le reste, et vous aurez des erreurs
(Il n'y a pas de caractère pour une ligne modifiée, car celles-ci sont gérées en supprimant l'ancienne ligne et en ajoutant celle modifiée en tant que nouvelle).

Puisque vous avez ouvert le diff dans votre éditeur de texte favori (vous avez bien configuré Git pour utiliser votre éditeur de texte préféré, n'est-ce pas?), Vous pouvez faire ce que vous voulez, à condition de vous assurer que le diff obtenu s'applique correctement.

Et c'est là que réside le truc. Si vous ne l'avez jamais fait auparavant, Git vous dira "Votre morceau édité ne s'applique pas. Éditez à nouveau?" si souvent, vous allez commencer à vous détester pour votre incapacité à comprendre cela, même si cela semble si facile (ou Git parce qu'il ne peut pas comprendre ce que vous voulez).

Une chose qui m'a souvent fait trébucher, c'est que j'ai oublié le retrait d'un personnage.
Je marquerais une ligne avec un - à supprimer, mais dans la plupart des éditeurs de texte insérant un -, cela n'écrase pas l'espace qui était auparavant. Cela signifie que vous ajoutez un espace supplémentaire à toute la ligne, ce qui signifie que l'algorithme diff ne peut pas trouver/faire correspondre la ligne dans le fichier d'origine, ce qui signifie que Git vous hurle.

L'autre chose est que le diff doit encore avoir un sens. "Sens" signifie qu'il peut être appliqué proprement. La façon exacte dont vous créez un diff sensible semble être un peu un art sombre (du moins pour moi à l’heure actuelle), mais vous devez toujours garder à l’esprit l’aspect du fichier original, puis planifier vos -s et + en conséquence. Si vous modifiez vos morceaux assez souvent, vous finirez par en prendre le contrôle.

Voir aussi ceci commit sur git add -p .

94
VonC

Bien sûr, je suis en retard par rapport à cela, mais je voulais néanmoins mentionner aux fins du compte rendu que cette question a été discutée l’année dernière sur la liste de diffusion git et il semble que peu de choses ont changé depuis.

Ce problème particulier provient de la scission de et essayer de modifier le même bloc. L'analyse, initialement publiée par Jeff King, du problème sous-jacent est essentiellement la suivante:

Hm. OK je vois. Le contrôle "Est-ce que diff s'applique" vérifie les flux les deux parties de le patch divisé à appliquer git. Mais bien sûr, la deuxième partie ne sera jamais appliquer correctement, car son contexte chevauche la première partie, mais ne le prend pas en compte.

Faire le contrôle avec seulement le correctif modifié fonctionnerait. Mais ça ne tient pas compte du fait que votre correctif modifié échouera potentiellement à appliquer à long terme, selon que vous acceptez ou non le l'autre moitié du split patch. Et nous ne pouvons pas encore le savoir, car le l’utilisateur ne l’aura peut-être pas dit (il aurait pu sauter la première moitié, puis puis y revenir plus tard, après l’édition). 

Jeff conclut son message avec une solution de contournement très pragmatique qui réussit toujours et qui est donc vivement recommandée:

Donc, en général, je pense que scinder et éditer le même morceau est inhérent dangereux et va conduire à ce genre de problèmes. Et parce que l'édition fournit un sur-ensemble de la fonctionnalité, je pense que vous devriez Il suffit d’éditer et d’autoriser la première partie du morceau à appliquer ou ne dépend pas de votre préférence. 

En choisissant uniquement de modifier un morceau non divisé auparavant, vous ne devrez pas vous occuper des numéros de ligne.

40
Niels Ganser

Lorsque vous ne souhaitez pas supprimer une ligne dont la suppression a été planifiée, comme dans

 first line
-second line
 third line

si vous souhaitez conserver la deuxième ligne, veillez à remplacer le - par un espace plutôt que de supprimer la ligne entière (comme vous le feriez pour vous débarrasser d'une ligne ajoutée). Git utilisera la ligne pour le contexte.

13
Rose Perrone

En lisant ce fil, j'ai récemment découvert comment travailler avec l'édition manuelle.

Le truc que j'ai utilisé était que si j'ai un diff comme celui-ci.

+ Line to add
+ Line to add
+ Line I dont want to include
+ Line I dont want to include

L'astuce consiste à supprimer les deux lignes que je ne veux pas rendre complètement le diff résultant ressemblant à ceci.

+ Line to add
+ Line to add

Bien que ce soit très probablement évident pour la plupart des gens, ce n'était pas pour moi jusqu'à aujourd'hui et j'ai pensé que je devrais partager mon expérience. S'il vous plaît dites-moi s'il y a un danger pour cette méthode.

11
Sedrik

Il est également important de modifier correctement l'en-tête du bloc (par exemple, @@ -1,6 +1,9 @@). Joaquin Windmuller révèle le secret de l’édition de l’en-tête dans un de ses blog posts .

Les secrets de l'édition de mecs

Éditer les mecs peut être déroutant au début, les instructions qui git vous donne de l'aide mais ne suffit pas pour commencer.

# —||

# To remove ‘-’ lines, make them ’ ’ lines (context).

# To remove ‘+’ lines, delete them.

# Lines starting with # will be removed.

#

# If the patch applies cleanly, the edited hunk will immediately be

# marked for staging. If it does not apply cleanly, you will be given

# an opportunity to edit again. If all lines of the hunk are removed,

# then the edit is aborted and the hunk is left unchanged.

La sauce secrète est… des lignes de comptage:

  • Si vous supprimez une ligne commençant par +, puis soustrayez-en une au nombre de nouvelles lignes (dernier chiffre de l’en-tête du bloc)).
  • Si vous supprimez une ligne commençant par - then ajoutez-en une au compte de nouvelles lignes (dernier chiffre de l’en-tête du bloc))}.
  • Ne supprimez pas les autres lignes (lignes de référence).

Cela devrait vous permettre de modifier rapidement les mecs pour sélectionner les parties tu veux.

6
Ortomala Lokni

Je suis venu à cette question à la recherche d'une solution au même problème, et je ne pouvais pas trouver comment changer les numéros de ligne (comme suggéré ci-dessus) dans le morceau pour obtenir l'acceptable dans mon cas. J'ai cependant trouvé une meilleure façon de le faire en utilisant git gui. Là, vous pouvez sélectionner les lignes dans le diff que vous souhaitez mettre en scène, puis faites un clic droit et choisissez "Mettre en scène les lignes de validation". Je me souviens que git-cola a les mêmes fonctionnalités.

6
Jayesh

Vous pouvez modifier manuellement les numéros de ligne, ce qui est certainement utile dans certains cas. Cependant, vous auriez probablement pu éviter ce problème particulier en ne divisant pas d'abord le morceau. 

Si vous voyez que vous aurez probablement besoin de modifier quelque chose plus tard dans le morceau choisi automatiquement par Git, il est préférable de simplement modifier le morceau en entier plutôt que de le scinder, de le placer par moitié et de le modifier ensuite. Git fera un meilleur travail pour résoudre ce problème.

6
Michael Hines

Un problème supplémentaire que j'ai eu lorsque j'ai eu cette erreur est que les fins de ligne ont changé lorsque j'ai enregistré le fichier de modification.

J'utilisais Windows et le Bloc-notes pour mes modifications (enregistre uniquement avec des fins de ligne Windows). Mon code a été écrit avec Notepad ++ et je l’ai configuré pour avoir des fins de ligne de style Unix/Linux.

Lorsque j'ai modifié mes paramètres pour avoir Notepad ++ en tant qu'éditeur git par défaut, j'ai pu modifier le morceau.

git config --global core.editor "notepad++"
5
KLee1

Une des raisons étranges des messages "Votre morceau modifié ne s'applique pas" (peut-être accompagnée de quelque chose comme "erreur: fragment de patch sans en-tête à la ligne ...") pourrait être votre éditeur s'il est configuré pour supprimer les espaces finaux. Cela poserait évidemment des problèmes majeurs, car les correctifs encodent les lignes vides sous forme de lignes avec un espace. Toute pièce contenant des lignes vides ne s'appliquerait pas si elle était enregistrée avec un tel éditeur. Donc, en réalité, tout morceau contenant des lignes vierges non modifiées ne pourra pas être appliqué après une édition avec si l'effacement des espaces à la fin est activé.

3
Timo

Pour votre information, je commençais à avoir une erreur légèrement inter-reliée ... quand j’ajoute patché en suivant les instructions suggérées ci-dessus ... Il ne montrait aucune erreur, cependant. Je le recevais à plusieurs reprises me demandant de mettre en scène le même morceau ... J'ai remarqué que j'utilisais une version plus ancienne de Vim 7.4 ... J'ai mis à jour vim et cela fonctionne comme prévu maintenant. Espérons que cela aidera quelqu'un ..

0
Mantisimo