`git am` always fails applying patch from `git format-patch -U0`
From: Nutchanon Wetchasit <hidden>
Date: 2020-05-05 12:04:11
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@example.com"
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 Attachments
- reproducing.log [text/x-log] 2714 bytes · preview