git am error: "patch does not apply"

I had the same problem. I had used

git format-patch <commit_hash>

to create the patch. My main problem was patch was failing due to some conflicts, but I could not see any merge conflict in the file content. I had used git am --3way <patch_file_path> to apply the patch.

The correct command to apply the patch should be:

git am --3way --ignore-space-change <patch_file_path>

If you execute the above command for patching, it will create a merge conflict if patch apply fails. Then you can fix the conflict in your files, like the same way merge conflicts are resolved for git merge


This kind of error can be caused by LF vs CRLF line ending mismatches, e.g. when you're looking at the patch file and you're absolutely sure it should be able to apply, but it just won't.

To test this out, if you have a patch that applies to just one file, you can try running 'unix2dos' or 'dos2unix' on just that file (try both, to see which one causes the file to change; you can get these utilities for Windows as well as Unix), then commit that change as a test commit, then try applying the patch again. If that works, that was the problem.

NB git am applies patches as LF by default (even if the patch file contains CRLF), so if you want to apply CRLF patches to CRLF files you must use git am --keep-cr, as per this answer.


git format-patch also has the -B flag.

The description in the man page leaves much to be desired, but in simple language it's the threshold format-patch will abide to before doing a total re-write of the file (by a single deletion of everything old, followed by a single insertion of everything new).

This proved very useful for me when manual editing was too cumbersome, and the source was more authoritative than my destination.

An example:

git format-patch -B10% --stdout my_tag_name > big_patch.patch
git am -3 -i < big_patch.patch

What is a patch?

A patch is little more (see below) than a series of instructions: "add this here", "remove that there", "change this third thing to a fourth". That's why Git tells you:

The copy of the patch that failed is found in:
c:/.../project2/.git/rebase-apply/patch

You can open that patch in your favorite viewer or editor, open the files-to-be-changed in your favorite editor, and "hand apply" the patch, using what you know (and Git does not) to figure out how "add this here" is to be done when the files-to-be-changed now look little or nothing like what they did when they were changed earlier, with those changes delivered to you as a patch.

A little more

A three-way merge introduces that "little more" information than the plain "series of instructions": it tells you what the original version of the file was as well. If your repository has the original version, your Git software, working in your repository, can compare what you did to a file, to what the patch says to do to the file.

As you saw above, if you request the three-way merge, Git can't find the "original version" in the other repository, so it can't even attempt the three-way merge. As a result you get no conflict markers, and you must do the patch-application by hand.

(There are cases where the "a little more" part is missing. The extra information is supplied by the Index: line in the patch, e.g.:

diff --git a/go.mod b/go.mod
index 1fefa60..38a3a41 100644

The second line may read, e.g.:

index 1fefa6021dcd205c1243e236d686595920d9621b..38a3a41434fda3a68ce3356092a89afca81eb614 100644

in more-complete cases. Note the two hash IDs, separated by two dots. The one on the left is the one your Git software will use, to attempt to find a file in your own repository that has the given hash ID. Applying the supplied patch to that file, which must exist, must work and must produce a file whose hash ID will be that on the right, and doing all of this gives Git all the additional information required.)

Using --reject

When you have to apply the patch by hand, it's still possible that Git can apply most of the patch for you automatically and leave only a few pieces to the entity with the ability to reason about the code (or whatever it is that needs patching). Adding --reject tells Git to do that, and leave the "inapplicable" parts of the patch in rejection files. If you use this option, you must still hand-apply each failing patch, and figure out what to do with the rejected portions.

Once you have made the required changes, you can git add the modified files and use git am --continue to tell Git to commit the changes and move on to the next patch.

What if there's nothing to do?

Since we don't have your code, I can't tell if this is the case, but sometimes, you wind up with one of the patches saying things that amount to, e.g., "fix the spelling of a word on line 42" when the spelling there was already fixed.

In this particular case, you, having looked at the patch and the current code, should say to yourself: "aha, this patch should just be skipped entirely!" That's when you use the other advice Git already printed:

If you prefer to skip this patch, run "git am --skip" instead.

If you run git am --skip, Git will skip over that patch, so that if there were five patches in the mailbox, it will end up adding just four commits, instead of five (or three instead of five if you skip twice, and so on).

Tags:

Git