问题
I\'m trying to use git add --interactive
to selectively add some changes to my index, but I continually receive the \"Your edited hunk does not apply. Edit again...\" message. I get this message even if I choose the e option, and immediately save/close my editor. In other words, without editing the hunk at all, the patch doesn\'t apply.
Here\'s the exact example I\'m using (I\'m trying to put together a small demo):
Original file:
first change
second change off branch
third change off branch
second change
third change
fourth change
New file:
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
I\'m trying to show how to use git add --interactive
to only add the \"bug fix 1\" line to the index. Running interactive add on the file, I choose the patch mode. It presents me with
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
I respond with split, followed by \"no\" to apply the first hunk. The second hunk, I try to edit. I originally tried deleting the bottom line - that didn\'t work. Leaving the hunk alone completely doesn\'t work either, and I can\'t figure out why.
回答1:
For this particular example, you need to tweak the line numbers in the hunk. Change the line:
@@ -1,6 +2,8 @@
so that it instead reads:
@@ -2,7 +2,8 @@
回答2:
Is this like in this git-add post?
Manually editing the hunk is immensely powerful, but also a bit complicated if you've never done it before.
The most important thing to keep in mind: The diff is always indented with one character in addition to whatever other indentation is there.
The character can either be:
- a space (indicates an unchanged line),
- a
-
indicating that the line was removed,- or a
+
indicating that the line was added.Nothing else. It must be either a space, a - or a +. Anything else, and you'll get errors
(there's no character for a changed line, since those are handled by removing the old line, and adding the changed one as new).Since you've got the diff open in your favorite text editor (you did configure Git to use your favorite text editor, right?), you can do whatever you want - as long as you make sure the resulting diff applies cleanly.
And therein lies the trick. If you've never done this before, Git will tell you "Your edited hunk does not apply. Edit again?" so often, you'll start to hate yourself for your inability to figure this out, even though it seems so easy (or Git because it can't figure out what you want).
One thing that tripped me up quite often was that I forgot the one character indent.
I'd mark a line with a - to be removed, but in most text editors that inserts a-
, it doesn't overwrite the space that was there before. This means you're adding an additional space to the whole line, which in turn means the diff algorithm can't find/match the line in the original file, which in turn means Git will yell at you.The other thing is that the diff still has to make sense. "Sense" means that it can be applied cleanly. Exactly how you create a sensible diff seems to be a bit of an dark art (at least to me right now), but you should always keep in mind how the original file looked like, and then plan your -s and +s accordingly. If you edit your hunks often enough you'll eventually get the hang of it.
See also this commit on git add -p.
Ortomala Lokni's answer refers to Joaquín Windmüller blog post "Selectively select changes to commit with git (or Imma edit your hunk)"
Instead of counting lines, what Git would like to do is to coalesce overlapping hunks (when one is edited) before applying said edited hunk.
That was discussed mid-2018, and would avoid scenario like:
if you split a hunk, edit the first subhunk, transforming a trailing context line to a deletion then if you try to stage the second subhunk, it will fail.
回答3:
Of course I'm late to this but nevertheless wanted to mention for the record that this issue was discussed last year on the git mailing list and it looks like not much has changed since.
This particular issue stems from splitting and attempting to edit the same hunk. The analysis, as originally posted by Jeff King, of the underlying problem essentially is:
Hm. OK, I see. The "does this diff apply" check feeds both parts of the split patch to git-apply. But of course the second part will never correctly apply, because its context overlaps with the first part, but doesn't take it into account.
Doing the check with just the edited patch would work. But that doesn't take into account that your edited patch will potentially fail to apply in the long run, depending on whether or not you accept the other half of the split patch. And we can't know that yet, because the user may not have told us (they could have skipped the first half, and then come back to it later after the edit step).
Jeff concludes his post with a very pragmatic workaround that always succeeds, and is thus highly recommended:
So in general, I think splitting and editing the same hunk is inherently dangerous and is going to lead to these sorts of problems. And because editing provides a superset of the functionality, I think you should just edit and either allow the first part of the hunk to be applied or not depending on your preference.
By only choosing to edit a hunk not previously split, you will not have to deal with the line numbers.
回答4:
When you want to not delete a line that staged for deletion, as in
first line
-second line
third line
where you want to keep the second line, make sure you replace the -
with a space, rather than deleting the whole line (as you would to get rid of an added line). Git will use the line for context.
回答5:
I recently figured out from reading this thread how to work the manual editing.
The trick I used was that if I have a diff like this.
+ Line to add
+ Line to add
+ Line I dont want to include
+ Line I dont want to include
The trick is to remove the two line I do not want completely making the resulting diff looking like this.
+ Line to add
+ Line to add
While this is most likley obvious to most people it was not for me until today and I thought I should just share my experience. Please tell me if there is any danger to this method.
回答6:
It's important to also correctly modify the hunk header (e.g. @@ -1,6 +1,9 @@
). Joaquin Windmuller reveal the secret of hunk header editing in one of his blog post.
The secrets of editing hunks
Editing the hunks can be confusing at first, the instructions that git gives you help but are not enough to get started.
# —|| # 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.
The secret sauce is…counting lines:
- If you remove a line that starts with + then subtract one to the new line count (last digit of the hunk’s header).
- If you remove a line that starts with - then add one to the new line count (last digit of the hunk’s header).
- Don’t remove the other lines (reference lines).
This should allow you to quickly modify the hunks to select the parts you want.
回答7:
You can manually edit the line numbers, that's definitely useful in some cases. However, you probably could have avoided this particular problem by NOT first splitting the hunk.
If you see that you'll probably need to edit something later in the hunk that Git has automatically chosen, it's best to just edit the whole hunk rather than splitting, staging half, and then editing the other half. Git will do a better job figuring that out.
回答8:
I came to this question looking for solution to same problem, and couldn't figure out how to change the line numbers (as suggested above) in the hunk to get git accept it in my case. I found a much better way to do that using git gui
though. There you can select the lines in the diff that you want to stage, then right click and choose "Stage lines from commit". I remember git-cola has the same functionality too.
回答9:
An additional problem I had when I got this error was that the line endings changed when I saved the edit file.
I was using Windows and using Notepad for my edits (only saves with Windows line-endings). My code was written with Notepad++ and I set it up to have Unix/Linux style line endings.
When I changed my settings to have Notepad++ as the default git editor I was able to make my edits to the hunk.
git config --global core.editor "notepad++"
回答10:
One reason for weird "Your edited hunk does not apply" messages (likely accompanied with something like "error: patch fragment without header at line...") might be your editor if it's configured to strip trailing whitespace. This would obviously cause major problems as patches encode empty lines as lines with one space any hunk containing empty lines would fail to apply if saved with such an editor. So in effect any hunk containing any unchanged empty lines would fail to apply after editing with if stripping trailing whitespace is on.
回答11:
FYI, I was getting a slightly interrelated error... when I add patched following the suggested instruction above... It was showing no error, however. I was getting it repeatedly asking me to stage the same hunk... I noticed I was running an older version of Vim 7.4... I upgraded vim and it's working as expected now. Hopefully this will help someone..
来源:https://stackoverflow.com/questions/3268596/git-add-interactive-your-edited-hunk-does-not-apply