Hello folks,
I was rewriting a committed change in my repository via a workflow
of git-format-patch -> edit -> git-am.
The edit I wanted to make was just a one-line change in the diff,
with no line number shift, so I generated patches with no context line
(`git format-patch -U0`) to avoid subsequent patch failure
caused by context change.
But the problem was that `git-am` appeared to erroneously
reject such patches for an unclear reason...
After editing patches, hard-resetting the branch to the parent commit
of the chain; I fed the patches to `git am`, and encountered an error
that looked like this:
> Applying: Removing second line
> error: patch failed: text.txt:2
> error: text.txt: patch does not apply
> Patch failed at 0001 Removing second line
> hint: Use 'git am --show-current-patch=diff' to see the failed 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".
The first thing I thought, was that I somehow messed up my patches
somewhere in the edit.
So I canceled the patching process with `git am --abort`,
hard-reset the branch again, and re-attempted running `git am`
with *unmodified* patches series;
and found that `git am` still produced the same error,
which ruled out the factor of my editing mistakes.
(Why would Git refuse a patch generated by itself?)
To be sure, I retried this on a dummy repository,
with only one non-modified zero-context patch;
and the error was still consistently reproducible.
I'm not sure what caused Git to reject such zero-context patches;
although some hints could be seen when running
`git apply --verbose` with the offending patch file.
(See step 9 in "Exact steps to reproduce" below)
GNU Patch would happily apply the same patch without any error though.
Nevertheless, this does not happen when the patch
was generated with 1 or more context lines.
So the workaround would be using `git format-patch -U1` instead,
with more risk of rejects on context change caused by editing.
-----
General steps to reproduce follows:
1. Make any disposable Git repository with two or more commits
on `master` branch.
2. Generate a zero-context patch of the latest commit with
`git format-patch -U0 HEAD^`
3. Remove the latest commit with `git reset --hard HEAD^`
4. Re-add the commit via the patch from step 2, with `git-am`;
it would claim that the patch does not apply.
Compare and contrast: try the same, but change step 2 to
`git format-patch -U1` HEAD^`, and you would see that `git-am`
accept it normally.
-----
Exact steps to reproduce follows:
1. Create an empty Git repository, with dummy user name and email:
$ mkdir am-nocontext
$ cd am-nocontext
$ git init
$ git config user.name "Joe Average"
$ git config user.email "joe@xxxxxxxxxxx"
2. Create a dummy 3-line text file, add it as the first commit:
$ printf "One\nTwo\nThree\n" > text.txt
$ git add text.txt
$ git commit -m "Initial commit"
3. Remove the second line from that file, make it a second commit:
$ printf "2d\nwq\n" | ed text.txt
$ git commit -am "Removing second line"
4. Generate patch from the second commit, with *zero* context line:
$ git format-patch -U0 HEAD^
5. Back out the second commit:
$ git reset --hard HEAD^
6. Add back the second commit using the patch from step 4:
$ git am 0001-Removing-second-line.patch
Applying: Removing second line
error: patch failed: text.txt:2
error: text.txt: patch does not apply
Patch failed at 0001 Removing second line
hint: Use 'git am --show-current-patch=diff' to see the failed 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".
^ You would find that Git reported that patching was failed,
when it should not be.
8. Cancel the patching process:
$ git am --abort
9. Try re-applying the same patch to the working tree using Git:
$ git apply --verbose 0001-Removing-second-line.patch
Checking patch text.txt...
error: while searching for:
Two
error: patch failed: text.txt:2
error: text.txt: patch does not apply
^ You would see that somehow Git tried to take the first line
in the hunk as a context, even when it wasn't marked as such.
10. Apply the same patch using GNU diffutils' `patch` program:
$ patch -p 1 -i 0001-Removing-second-line.patch
patching file text.txt
$ git diff
diff --git a/text.txt b/text.txt
index 4fcefbf..3146b8f 100644
--- a/text.txt
+++ b/text.txt
@@ -1,3 +1,2 @@
One
-Two
Three
^ You would find that GNU Patch would apply
the same patch correctly.
The full terminal transcript is attached as
<attachment:reproducing.log>,
which also includes intermediate informational steps,
and also displays the exact patch content produced by the process.
-----
System information follows...
Git: 2.26.2 (source)
Patch: GNU diffutils 2.6.1 (Debian)
System: Debian GNU/Linux 7.0 Wheezy i386
Locale: th_TH (local encoding TIS-620)
Note that this problem appears to exist for long way down to at least
Git 1.7.10.4 (the original version I found this error), if not earlier.
Please advice in case I overlooked something.
Regards,
Nutchanon Wetchasit
$ cd /tmp
$ mkdir am-nocontext
$ cd am-nocontext
$ git init
Initialized empty Git repository in /tmp/am-nocontext/.git/
$ git config user.name "Joe Average"
$ git config user.email "joe@xxxxxxxxxxx"
$ printf "One\nTwo\nThree\n" > text.txt
$ cat text.txt
One
Two
Three
$ git add text.txt
$ git commit -m "Initial commit"
[master (root-commit) e2e0c16] Initial commit
1 file changed, 3 insertions(+)
create mode 100644 text.txt
$ git log --pretty=oneline
e2e0c16f6d31bc8e673494ecc92d1e8f377275aa (HEAD -> master) Initial commit
$ printf "2d\nwq\n" | ed text.txt
14
10
$ cat text.txt
One
Three
$ git diff
diff --git a/text.txt b/text.txt
index 4fcefbf..3146b8f 100644
--- a/text.txt
+++ b/text.txt
@@ -1,3 +1,2 @@
One
-Two
Three
$ git commit -am "Removing second line"
[master 27e6e8b] Removing second line
1 file changed, 1 deletion(-)
$ git log --pretty=oneline
27e6e8bdc3ecbecc17f5ec1407f97f1977054461 (HEAD -> master) Removing second line
e2e0c16f6d31bc8e673494ecc92d1e8f377275aa Initial commit
$ git format-patch -U0 HEAD^
0001-Removing-second-line.patch
$ cat 0001-Removing-second-line.patch
>From 27e6e8bdc3ecbecc17f5ec1407f97f1977054461 Mon Sep 17 00:00:00 2001
From: Joe Average <joe@xxxxxxxxxxx>
Date: Tue, 5 May 2020 18:17:52 +0700
Subject: [PATCH] Removing second line
---
text.txt | 1 -
1 file changed, 1 deletion(-)
diff --git a/text.txt b/text.txt
index 4fcefbf..3146b8f 100644
--- a/text.txt
+++ b/text.txt
@@ -2 +1,0 @@ One
-Two
--
2.26.2
$ git reset --hard HEAD^
HEAD is now at e2e0c16 Initial commit
$ git log --pretty=oneline
e2e0c16f6d31bc8e673494ecc92d1e8f377275aa (HEAD -> master) Initial commit
$ git am 0001-Removing-second-line.patch
Applying: Removing second line
error: patch failed: text.txt:2
error: text.txt: patch does not apply
Patch failed at 0001 Removing second line
hint: Use 'git am --show-current-patch=diff' to see the failed 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 --abort
$ git diff
$ git log --pretty=oneline
e2e0c16f6d31bc8e673494ecc92d1e8f377275aa (HEAD -> master) Initial commit
$ git apply --verbose 0001-Removing-second-line.patch
Checking patch text.txt...
error: while searching for:
Two
error: patch failed: text.txt:2
error: text.txt: patch does not apply
$ git log --pretty=oneline
e2e0c16f6d31bc8e673494ecc92d1e8f377275aa (HEAD -> master) Initial commit
$ git diff
$ patch -p 1 -i 0001-Removing-second-line.patch
patching file text.txt
$ git diff
diff --git a/text.txt b/text.txt
index 4fcefbf..3146b8f 100644
--- a/text.txt
+++ b/text.txt
@@ -1,3 +1,2 @@
One
-Two
Three
$ exit