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