{"thread":{"id":"53400","subject":"`git am` always fails applying patch from `git format-patch -U0`","startedAt":"2020-05-05T12:04:11Z","lastAt":"2020-05-05T12:04:11Z","messageCount":1,"participants":["Nutchanon Wetchasit"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"397082","messageId":"20200505190338.1155dcfd@WINDOW-NB","threadId":"53400","inReplyTo":null,"subject":"`git am` always fails applying patch from `git format-patch -U0`","fromName":"Nutchanon Wetchasit","fromEmail":"nutchanon.wetchasit@gmail.com","sentAt":"2020-05-05T12:03:38Z","receivedAt":"2020-05-05T12:04:11Z","isPatch":false,"sender":{"key":"nutchanon.wetchasit@gmail.com","avatar":null},"body":"Hello folks,\n\nI was rewriting a committed change in my repository via a workflow\nof git-format-patch -> edit -> git-am.\n\nThe edit I wanted to make was just a one-line change in the diff,\nwith no line number shift, so I generated patches with no context line\n(`git format-patch -U0`) to avoid subsequent patch failure\ncaused by context change.\n\nBut the problem was that `git-am` appeared to erroneously\nreject such patches for an unclear reason...\n\nAfter editing patches, hard-resetting the branch to the parent commit\nof the chain; I fed the patches to `git am`, and encountered an error\nthat looked like this:\n\n> Applying: Removing second line\n> error: patch failed: text.txt:2\n> error: text.txt: patch does not apply\n> Patch failed at 0001 Removing second line\n> hint: Use 'git am --show-current-patch=diff' to see the failed patch\n> When you have resolved this problem, run \"git am --continue\".\n> If you prefer to skip this patch, run \"git am --skip\" instead.\n> To restore the original branch and stop patching, run \"git am --abort\".\n\nThe first thing I thought, was that I somehow messed up my patches\nsomewhere in the edit.\n\nSo I canceled the patching process with `git am --abort`,\nhard-reset the branch again, and re-attempted running `git am`\nwith *unmodified* patches series;\nand found that `git am` still produced the same error,\nwhich ruled out the factor of my editing mistakes.\n(Why would Git refuse a patch generated by itself?)\n\nTo be sure, I retried this on a dummy repository,\nwith only one non-modified zero-context patch;\nand the error was still consistently reproducible.\n\nI'm not sure what caused Git to reject such zero-context patches;\nalthough some hints could be seen when running\n`git apply --verbose` with the offending patch file.\n(See step 9 in \"Exact steps to reproduce\" below)\n\nGNU Patch would happily apply the same patch without any error though.\n\nNevertheless, this does not happen when the patch\nwas generated with 1 or more context lines.\nSo the workaround would be using `git format-patch -U1` instead,\nwith more risk of rejects on context change caused by editing.\n\n-----\n\nGeneral steps to reproduce follows:\n\n1. Make any disposable Git repository with two or more commits\n   on `master` branch.\n\n2. Generate a zero-context patch of the latest commit with\n   `git format-patch -U0 HEAD^`\n\n3. Remove the latest commit with `git reset --hard HEAD^`\n\n4. Re-add the commit via the patch from step 2, with `git-am`;\n   it would claim that the patch does not apply.\n\nCompare and contrast: try the same, but change step 2 to\n`git format-patch -U1` HEAD^`, and you would see that `git-am`\naccept it normally.\n\n-----\n\nExact steps to reproduce follows:\n\n 1. Create an empty Git repository, with dummy user name and email:\n    \n    $ mkdir am-nocontext\n    $ cd am-nocontext\n    $ git init\n    $ git config user.name \"Joe Average\"\n    $ git config user.email \"joe@example.com\"\n    \n 2. Create a dummy 3-line text file, add it as the first commit:\n    \n    $ printf \"One\\nTwo\\nThree\\n\" > text.txt\n    $ git add text.txt\n    $ git commit -m \"Initial commit\"\n    \n 3. Remove the second line from that file, make it a second commit:\n    \n    $ printf \"2d\\nwq\\n\" | ed text.txt\n    $ git commit -am \"Removing second line\"\n    \n 4. Generate patch from the second commit, with *zero* context line:\n    \n    $ git format-patch -U0 HEAD^\n    \n 5. Back out the second commit:\n    \n    $ git reset --hard HEAD^\n    \n 6. Add back the second commit using the patch from step 4:\n    \n    $ git am 0001-Removing-second-line.patch\n    Applying: Removing second line\n    error: patch failed: text.txt:2\n    error: text.txt: patch does not apply\n    Patch failed at 0001 Removing second line\n    hint: Use 'git am --show-current-patch=diff' to see the failed patch\n    When you have resolved this problem, run \"git am --continue\".\n    If you prefer to skip this patch, run \"git am --skip\" instead.\n    To restore the original branch and stop patching, run \"git am --abort\".\n    \n    ^ You would find that Git reported that patching was failed,\n      when it should not be.\n    \n 8. Cancel the patching process:\n    \n    $ git am --abort\n    \n 9. Try re-applying the same patch to the working tree using Git:\n    \n    $ git apply --verbose 0001-Removing-second-line.patch\n    Checking patch text.txt...\n    error: while searching for:\n    Two\n    \n    error: patch failed: text.txt:2\n    error: text.txt: patch does not apply\n    \n    ^ You would see that somehow Git tried to take the first line\n      in the hunk as a context, even when it wasn't marked as such.\n    \n10. Apply the same patch using GNU diffutils' `patch` program:\n    \n    $ patch -p 1 -i 0001-Removing-second-line.patch\n    patching file text.txt\n    $ git diff\n    diff --git a/text.txt b/text.txt\n    index 4fcefbf..3146b8f 100644\n    --- a/text.txt\n    +++ b/text.txt\n    @@ -1,3 +1,2 @@\n     One\n    -Two\n     Three\n    \n    ^ You would find that GNU Patch would apply\n      the same patch correctly.\n\nThe full terminal transcript is attached as\n<attachment:reproducing.log>,\nwhich also includes intermediate informational steps,\nand also displays the exact patch content produced by the process.\n\n-----\n\nSystem information follows...\n\n   Git: 2.26.2 (source)\n Patch: GNU diffutils 2.6.1 (Debian)\nSystem: Debian GNU/Linux 7.0 Wheezy i386\nLocale: th_TH (local encoding TIS-620)\n\nNote that this problem appears to exist for long way down to at least\nGit 1.7.10.4 (the original version I found this error), if not earlier.\n\nPlease advice in case I overlooked something.\n\nRegards,\nNutchanon Wetchasit\n\n$ cd /tmp\n$ mkdir am-nocontext\n$ cd am-nocontext\n$ git init\nInitialized empty Git repository in /tmp/am-nocontext/.git/\n$ git config user.name \"Joe Average\"\n$ git config user.email \"joe@example.com\"\n$ printf \"One\\nTwo\\nThree\\n\" > text.txt\n$ cat text.txt\nOne\nTwo\nThree\n$ git add text.txt\n$ git commit -m \"Initial commit\"\n[master (root-commit) e2e0c16] Initial commit\n 1 file changed, 3 insertions(+)\n create mode 100644 text.txt\n$ git log --pretty=oneline\ne2e0c16f6d31bc8e673494ecc92d1e8f377275aa (HEAD -> master) Initial commit\n$ printf \"2d\\nwq\\n\" | ed text.txt\n14\n10\n$ cat text.txt\nOne\nThree\n$ git diff\ndiff --git a/text.txt b/text.txt\nindex 4fcefbf..3146b8f 100644\n--- a/text.txt\n+++ b/text.txt\n@@ -1,3 +1,2 @@\n One\n-Two\n Three\n$ git commit -am \"Removing second line\"\n[master 27e6e8b] Removing second line\n 1 file changed, 1 deletion(-)\n$ git log --pretty=oneline\n27e6e8bdc3ecbecc17f5ec1407f97f1977054461 (HEAD -> master) Removing second line\ne2e0c16f6d31bc8e673494ecc92d1e8f377275aa Initial commit\n$ git format-patch -U0 HEAD^\n0001-Removing-second-line.patch\n$ cat 0001-Removing-second-line.patch\nFrom 27e6e8bdc3ecbecc17f5ec1407f97f1977054461 Mon Sep 17 00:00:00 2001\nFrom: Joe Average <joe@example.com>\nDate: Tue, 5 May 2020 18:17:52 +0700\nSubject: [PATCH] Removing second line\n\n---\n text.txt | 1 -\n 1 file changed, 1 deletion(-)\n\ndiff --git a/text.txt b/text.txt\nindex 4fcefbf..3146b8f 100644\n--- a/text.txt\n+++ b/text.txt\n@@ -2 +1,0 @@ One\n-Two\n-- \n2.26.2\n\n$ git reset --hard HEAD^\nHEAD is now at e2e0c16 Initial commit\n$ git log --pretty=oneline\ne2e0c16f6d31bc8e673494ecc92d1e8f377275aa (HEAD -> master) Initial commit\n$ git am 0001-Removing-second-line.patch\nApplying: Removing second line\nerror: patch failed: text.txt:2\nerror: text.txt: patch does not apply\nPatch failed at 0001 Removing second line\nhint: Use 'git am --show-current-patch=diff' to see the failed patch\nWhen you have resolved this problem, run \"git am --continue\".\nIf you prefer to skip this patch, run \"git am --skip\" instead.\nTo restore the original branch and stop patching, run \"git am --abort\".\n$ git am --abort\n$ git diff\n$ git log --pretty=oneline\ne2e0c16f6d31bc8e673494ecc92d1e8f377275aa (HEAD -> master) Initial commit\n$ git apply --verbose 0001-Removing-second-line.patch\nChecking patch text.txt...\nerror: while searching for:\nTwo\n\nerror: patch failed: text.txt:2\nerror: text.txt: patch does not apply\n$ git log --pretty=oneline\ne2e0c16f6d31bc8e673494ecc92d1e8f377275aa (HEAD -> master) Initial commit\n$ git diff\n$ patch -p 1 -i 0001-Removing-second-line.patch\npatching file text.txt\n$ git diff\ndiff --git a/text.txt b/text.txt\nindex 4fcefbf..3146b8f 100644\n--- a/text.txt\n+++ b/text.txt\n@@ -1,3 +1,2 @@\n One\n-Two\n Three\n$ exit\n"}]}