Solving git am failures

by Tsvi Mostovicz - Sun 23 March 2025
Tags #Git
Reading time: 2 minutes, 19 seconds

When you need to bring over patches from one repo (we'll call it repoA) to another (repoB) without being able to pull, one of the tools to do that would be git am.

You create a few patch files by calling git format-patch HEAD and git will create a patch file for you.

You can create multiple patch files (one per commit) by providing a range of commits.

Applying the patch

Now that you have a patch file, you can apply them to the other repo (repoB):

cd /path/to/repoB
git am -3 /path/to/the/patch/files/from/repoA/000*

The -3 switch tells git to do a three-way merge in case it's unable to apply the patch cleanly.

Understanding the concept of the three-way merge

When git does merges, it understands them in terms of commits. So when you apply a patch to a file, it looks at the SHA-1 checksum of the original file and at the SHA-1 checksum noted in the patch file.

E.g.:

index 9be63806d8bb..58b2693fcf9b 100644

This means that the original file's SHA-1 should start with 9be63806d8bb. If this is not the same in our repoB, we cannot apply the patch cleanly.

In a three-way merge, git looks for another blob that with the given SHA-1 so that it might create a merge between 9be63806d8bb, the current SHA-1 of the blob, and the patch file.

This could happen if in the repoB, we have another commit after 9be63806d8bb.

What if the commit in the original repo is newer

Let's continue with our example. What if we can't find 9be63806d8bb in repoB, because repoA has a newer version of the file who's changes were never applied to repoB?

In such a case the -3 flag won't help us.

git am will stop, and ask us to apply the patch manually, after which we can call git am --continue so it can continue processing patches.

To do this, I suggest the following one-liner:

git am --show-current-patch=diff | git apply --reject --whitespace=fix -

This will tell git to print to stdout the current patch as a diff file, ant passes it to git apply.

With the --reject flag, parts that don't apply cleanly will be passed to a *.rej file, where you might to copy them manually.

Now you can go ahead and do git add <path to files changed by git apply>, and git am --continue.

Enjoy,

Tsvi

Comments