git add --interactive "Your edited hunk does not apply"
Asked Answered
H

13

99

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.

Hackler answered 16/7, 2010 at 20:23 Comment(2)
A good thing to make sure of here is that you aren't adding -'s at the beginning of lines that don't exist in the file to begin with; it's a diff and it can't delete lines that aren't already there. So if a line in the diff begins with + and you change it to - git goes WTF? because now the line marked for removal doesn't exist to begin with (instead that line was marked for addition, and when a line marked for addition is marked for removal git can't remove a line that isn't already in the file).Burnaby
Check also line endings (LF, CRLF) in my case it didn't apply for one LF instead of CRLF!Zook
T
39

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 @@
Teresiateresina answered 17/7, 2010 at 8:44 Comment(12)
After some digging, I found that those lines are showing the "from-file range" and "to-file range". I don't really understand the logic behind changing the 1 to a 2. I tried it, and it works, but I don't understand why the "from-file range" changes. The original file is the same, whether I'm applying the whole patch, or just the edited hunk. Can you clarify further, or point me to a descent reference on the unified diff format. I've been unsuccessful in finding one.Hackler
@Josh: #2529941 can help, even if I don't get entirely the Unified format hunks. @William +1Krute
@Josh: In looking into it it looks like it may be a bug. After you edit the hunk, git attempts to verify the patch by checking that all hunks will apply (this may be excessive). Unfortunately, in this case, that means the previous hunk (which you are not applying) is being checked, and there is some overlap which causes git apply --check to fail. I don't know an elegant solution; git may be doing the right thing by being overly cautious here.Teresiateresina
More info on changing the line numbers please? Why do we have to do that? And how? What does each number mean?Halfblooded
What? I don’t understand what any of this means.Extravehicular
Where is @@ -1,6 +2,8 @@ line?Monaghan
When you are in the interactive mode and split the first hunk, the second hunk has that line.Teresiateresina
Looks like modern versions of git handle this properly, though.Teresiateresina
@WilliamPursell what versions of git? I've switched to a new computer and running git v2.17.0 and all of a sudden my patch edits are never valid anymore.Asperges
@Asperges I'm experiencing the same thing with git 2.18.0Raffarty
Experiencing the same also for a while now (I think it was from 2.17)....Holler
How does this answer help understanding the problem and the solution? It is sad that people mark such post as "accepted answer" only because it solves their current problem but explains absolutely nothing, and ignoring better answers which not only solve the problems but explains it as well.Expatiate
K
128

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 insert a -, it doesn't overwrite the space that was there before. This means you're adding another 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 scenarios 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.


With Git 2.45 (Q2 2024), batch 16, "git add -p"(man) and other interactive hunk selection UI has learned to skip showing the hunk immediately after it has already been shown, and an additional action to explicitly ask to reshow the current hunk.

In your case, the hunk which does not apply will not be repeated after a "Your edited hunk does not apply. Edit again..." error message.

See commit bab1f1c, commit 66c14ab (29 Mar 2024) by Rubén Justo (rjusto).
(Merged by Junio C Hamano -- gitster -- in commit 989bf45, 09 Apr 2024)

add-patch: do not print hunks repeatedly

Signed-off-by: Rubén Justo

The interactive-patch is a sequential process where, on each step, we print one hunk from a patch and then ask the user how to proceed.

There is a possibility of repeating a step, for example if the user enters a non-applicable option, i.e: "s"

$ git add -p
diff --git a/add-patch.c b/add-patch.c
index 52be1ddb15..8fb75e82e2 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -1394,7 +1394,7 @@ N_("j - leave this hunk undecided, see next undecided hunk\n"
 static int patch_update_file(struct add_p_state *s,
               struct file_diff *file_diff)
 {
- size_t hunk_index = 0;
+ size_t hunk_index = 0, prev_hunk_index = -1;
  ssize_t i, undecided_previous, undecided_next;
  struct hunk *hunk;
  char ch;
(1/4) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? s
Sorry, cannot split this hunk
@@ -1394,7 +1394,7 @@ N_("j - leave this hunk undecided, see next undecided hunk\n"
 static int patch_update_file(struct add_p_state *s,
               struct file_diff *file_diff)
 {
- size_t hunk_index = 0;
+ size_t hunk_index = 0, prev_hunk_index = -1;
  ssize_t i, undecided_previous, undecided_next;
  struct hunk *hunk;
  char ch;
(1/4) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?

...
or an invalid option, i.e: "U"

$ git add -p
diff --git a/add-patch.c b/add-patch.c
index 52be1ddb15..8fb75e82e2 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -1394,7 +1394,7 @@ N_("j - leave this hunk undecided, see next undecided hunk\n"
 static int patch_update_file(struct add_p_state *s,
               struct file_diff *file_diff)
 {
- size_t hunk_index = 0;
+ size_t hunk_index = 0, prev_hunk_index = -1;
  ssize_t i, undecided_previous, undecided_next;
  struct hunk *hunk;
  char ch;
(1/4) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? U
y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk or any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk or any of the later hunks in the file
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
g - select a hunk to go to
/ - search for a hunk matching the given regex
e - manually edit the current hunk
p - print again the current hunk
? - print help
@@ -1394,7 +1394,7 @@ N_("j - leave this hunk undecided, see next undecided hunk\n"
 static int patch_update_file(struct add_p_state *s,
               struct file_diff *file_diff)
 {
- size_t hunk_index = 0;
+ size_t hunk_index = 0, prev_hunk_index = -1;
  ssize_t i, undecided_previous, undecided_next;
  struct hunk *hunk;
  char ch;
(1/4) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?

Printing the chunk again followed by the question can be confusing as the user has to pay special attention to notice that the same chunk is being reconsidered.

It can also be problematic if the chunk is longer than one screen height because the result of the previous iteration is lost off the screen (the help guide in the previous example).

To avoid such problems, stop printing the chunk if the iteration does not advance to a different chunk.

But you also have:

add-patch: introduce 'p' in interactive-patch

Signed-off-by: Rubén Justo

Shortly we're going make interactive-patch stop printing automatically the hunk under certain circumstances.

Let's introduce a new option to allow the user to explicitly request the printing.

git add now includes in its man page:

p - print the current hunk

You can inspect at any time the current hunk in your interractive patch session with p.

Krute answered 16/7, 2010 at 20:39 Comment(8)
Thanks for the link, but I had already seen this. I was not adding/leaving an additional line. The problem was in the line numbers, but I still don't understand the fix.Hackler
I was not replacing a deleted '-' with a blank space - thus screwing up the indentation. Thx!!Egalitarian
Just make sure you don't misunderstand the blank space part. I thought all unchanged lines should be just a line with a black - instead of merely the indent character ... Had an hour of "edited hunk does not apply" until I understood why :-/Pusher
@Pusher I am not sure I understand you: what did you had to do to make your edited hunk apply?Krute
@VonC: I first thought I should change - foo into ` ` (just a blank space, not "a blank space and the entire line"). Took me a while to understand it should have been ` foo`.Pusher
@Pusher Got it. Thank you for clarifying.Krute
Whatever you do. See @Ortomala Lokni's post below. There is critical information there about additional edits that is not discussed above.Calcar
Thanks for the "or a space". I hate significant (and invisible!) whitespacePlatinotype
P
62

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.

Promotion answered 21/12, 2010 at 14:45 Comment(6)
Thanks, this is indeed way easier than fiddling about with line numbers.Ethridge
This was my issue. Needed my hunk to be smaller. Performed a split in interactive. The split was not what I wanted so I decided to try and edit manually. Kept getting the error. Started over, worked first try.Messenger
This is the best answer in this thread. Do not split and edit. Just edit.Cornflower
In my case, an extra problem was coming from Windows line endings shown as ^M in the diff file. Once I saved the file with CR endings, the interactive edit patch went through!Cornflower
Thanks, this did the trick for me. I had to work on a huge chunk, so I split it down, and everything broke. Keeping it unsplit made everything work fine.Outrage
Argh, why doesn't git just say «Sorry, you can't edit an already split hunk» instead of blaming the user that it «does not apply»? This is a bug: A bug is a deviation between spec and result. As such, when the user follows the edit rules correctly, and it doesn't work, it's a bug.Addieaddiego
T
39

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 @@
Teresiateresina answered 17/7, 2010 at 8:44 Comment(12)
After some digging, I found that those lines are showing the "from-file range" and "to-file range". I don't really understand the logic behind changing the 1 to a 2. I tried it, and it works, but I don't understand why the "from-file range" changes. The original file is the same, whether I'm applying the whole patch, or just the edited hunk. Can you clarify further, or point me to a descent reference on the unified diff format. I've been unsuccessful in finding one.Hackler
@Josh: #2529941 can help, even if I don't get entirely the Unified format hunks. @William +1Krute
@Josh: In looking into it it looks like it may be a bug. After you edit the hunk, git attempts to verify the patch by checking that all hunks will apply (this may be excessive). Unfortunately, in this case, that means the previous hunk (which you are not applying) is being checked, and there is some overlap which causes git apply --check to fail. I don't know an elegant solution; git may be doing the right thing by being overly cautious here.Teresiateresina
More info on changing the line numbers please? Why do we have to do that? And how? What does each number mean?Halfblooded
What? I don’t understand what any of this means.Extravehicular
Where is @@ -1,6 +2,8 @@ line?Monaghan
When you are in the interactive mode and split the first hunk, the second hunk has that line.Teresiateresina
Looks like modern versions of git handle this properly, though.Teresiateresina
@WilliamPursell what versions of git? I've switched to a new computer and running git v2.17.0 and all of a sudden my patch edits are never valid anymore.Asperges
@Asperges I'm experiencing the same thing with git 2.18.0Raffarty
Experiencing the same also for a while now (I think it was from 2.17)....Holler
How does this answer help understanding the problem and the solution? It is sad that people mark such post as "accepted answer" only because it solves their current problem but explains absolutely nothing, and ignoring better answers which not only solve the problems but explains it as well.Expatiate
A
26

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.

Azral answered 24/1, 2018 at 16:58 Comment(3)
Is there a way to automate the editing of the hunk header or configure git to determine the appropriate line counts?Asperges
You can probably script your favorite editor to automatize this. Maybe there is already some plugins for this, but this is editor dependent.Azral
I had this problem using git in Windows. I've found that you don't have to do any line counting or tweak with the header. If Vim is the active editor, simply set the line endings to Unix sometime before your write/quit and git will figure it out. :set ff=unixBriolette
W
19

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.

Wisner answered 24/3, 2013 at 22:18 Comment(1)
This wasn't clear to me, I thought Git was telling me to make the line a single space.Sarcoma
S
17

I recently figured out from reading this thread how to do the manual editing.

The trick I used was that if I have a diff like:

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

The trick is to completely remove the two lines I don't want, making the resulting diff looking like:

+ Line to add
+ Line to add

While this is most likely 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.

Scribbler answered 7/4, 2011 at 8:6 Comment(3)
I can't thank you enough! I was trying to change the + into a ' ' for at least an hour.Raphael
You know, craziness is doing the same thing and expecting a different result. I've been saying that to myself for 20 minutes before I figured out that I just needed to delete :)Barbellate
This should be the answer. Nice and simple, thanks!Domela
M
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.

Mimamsa answered 20/3, 2012 at 18:5 Comment(0)
J
6

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.

Jennee answered 6/10, 2011 at 8:14 Comment(1)
This really ought to be the answer. git-cola appears to work on Linux, Windows, and MacOS.Burnaby
E
6

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.

Exaggerated answered 20/6, 2018 at 14:33 Comment(0)
M
5

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++"
Mauromaurois answered 12/11, 2012 at 21:3 Comment(2)
This worked for me. But I needed the full path to notepad++ and that took a while to get right: git config --global core.editor '"C:/Program\ Files\ \(x86\)/Notepad++/notepad++.exe"' (adapt this according to where notepad++ is installed on your PC)Tonitonia
Exact same problem for me. It was Notepad that was causing problems. Once I switched my default editor to Notepad++, everything started to work again.Vocalise
A
2

The issue might be in general that the patch wasn't done correctly or a more specific issue that I will describe in the bottom of the post,

How to Edit in VIM

The way you should do it if vim is the editor, is by placing the cursor over the first character in the line, and do the following (assuming you are in command mode which is the default or after pressing esc) based on the current character and what you want to do:

  1. For a line that starts with a ' ' space which means unchanged:

    • If you want to DELETE it then type r-
  2. For a line that starts with a '-' which means it will be removed (or replaced):

    • If you do NOT want to delete it then type r (that's r and then space)
    • Be careful with the order of the lines, see below
  3. For a line that was stars with a '+' which means it will be add (or replace the '-' line before):

    • If you do NOT want to add it then type dd

Handling the line order issue

Also you would probably want to move around lines so that the + line is right after the - line otherwise the + added line will be moved after the unchanged lines, as in this example:

Say you have the following patch before editing:

-Line1
-Line2
+NewLine1
+NewLine2

And you want to only stage the first line, the DO NOT do the following:

-Line1
Line2
+NewLine1

as it will cause NewLine1 to end up AFTER Line2! (unless this is what you want), instead move around the lines using the VIM commands described here

Saving

Once you are done just type :wq and you should be fine.

Another cause of the error

You can also get this error message (even if you did everything correctly) if while going through the patches git add the changes were also modified externally.

(For example you used another terminal or GUI to stage changes.)

This causes the line numbers to fail when actually trying to apply the changes.

In this case you should rather quit first (by using 'q' etc.) and then restart.

Alard answered 21/10, 2021 at 21:11 Comment(0)
B
1

I used to have this problem. If doing an interactive add in windows, using VIM, you don't have to tweak the hunk header (the stuff between the @@'s), all you have to do is set the file line endings to Unix (LF).

In the VIM editor, simply do the following command sometime before your write/quit:

:set ff=unix
Briolette answered 5/2, 2021 at 19:48 Comment(0)
P
0

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..

Perineum answered 26/12, 2018 at 16:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.