TechEarl

Export and Apply Patches With git format-patch and git am

Move changes between Git repos as patch files. git diff plus git apply for a quick change transfer, or git format-patch plus git am to recreate the commits with their author, date, and message intact.

Ishan Karunaratne⏱️ 7 min readUpdated
Share thisCopied
Export Git changes as patch files with git diff or git format-patch, then apply them in another repo with git apply or git am to preserve authorship.

The fastest way to move a change from one Git repo to another without a shared remote is a patch file. There are two flavors, and picking the right one is the whole game. If you just want the changes, use git diff to export and git apply to apply:

bash
# In the source repo: write the working-tree changes to a file
git diff > my.patch

# In the target repo: apply them (no commit, no author, no message)
git apply my.patch

That transfers the edits as a raw diff. It does not create a commit, and it carries no author, date, or message. If you want the commits (author, date, and log message preserved), use git format-patch to export and git am to apply:

bash
# In the source repo: one .patch file per commit, last 3 commits
git format-patch -3

# In the target repo: replay them as commits
git am *.patch

That recreates each commit on the target branch exactly as it was, original author and all. The rest of this page is when to reach for which, and the flags that save you when a patch does not apply cleanly.

git diff plus git apply: a quick change transfer

git diff > my.patch captures whatever your working tree has changed against HEAD into a plain unified diff. git apply my.patch in another checkout replays those line edits. No commit is created, nothing is staged, and the patch has no notion of who wrote it or why. It is the right tool when you just want to hand someone a change and you do not care about commit history: a one-off fix, a config tweak, moving an experiment between two clones.

Want only what is already staged instead of the whole working tree? Add --cached (also spelled --staged):

bash
git diff --cached > staged.patch

By default git apply only touches the working tree, not the index. If you want the applied changes staged in one step, add --index:

bash
git apply --index my.patch

git format-patch plus git am: preserve authorship

git format-patch is the classic "email a patch" workflow, the one the Linux kernel and most mailing-list projects still run on. It writes one file per commit, each formatted as an mbox-style email complete with the author, date, subject (the commit summary), and full commit body. You pick the range of commits to export:

bash
# The last N commits, numbered 0001-, 0002-, ...
git format-patch -3

# Every commit on feature that is not on main
git format-patch main..feature

# Just the most recent commit
git format-patch -1 HEAD

# Everything on this branch that is not on origin/main
git format-patch origin/main..HEAD

# Drop the files into a directory instead of the current folder
git format-patch -3 -o patches/

# A single combined file on stdout instead of one-per-commit
git format-patch main --stdout > feature.patch

On the receiving end, git am ("apply mailbox") reads those files, splits each back into its metadata and diff, and creates a commit per patch. Because the author and date rode along in the file, the replayed commits keep the original authorship rather than being attributed to whoever ran the command:

bash
# Apply every patch file in order, recreating the commits
git am *.patch

Add --signoff (or -s) if the project expects a Signed-off-by trailer on incoming patches:

bash
git am --signoff *.patch

If git am stops on a conflict, git am --abort rewinds you to where you started, git am --skip drops the current patch, and git am --continue resumes after you have resolved the conflict and staged the fix.

When to use which

You wantExportApplyAuthorship and history
A quick change moved overgit diff > my.patchgit apply my.patchNone preserved, no commit created
The commits recreated faithfullygit format-patch <range>git am *.patchAuthor, date, and message kept

The short rule: git apply for a change transfer, git format-patch plus git am when you need to preserve authorship. If you are going to throw the diff away after one apply, the diff/apply path is less ceremony. If the work is real commits you want to land intact in another tree, format-patch and am are worth the extra step.

Dry-run before you apply

git apply --check tells you whether a patch will apply cleanly without changing anything. Run it first whenever you did not generate the patch yourself:

bash
# Will it apply? No changes made, just success or an error.
git apply --check my.patch

# What files and how many lines would it touch?
git apply --stat my.patch

A clean --check exits silently with status 0. Anything else (a "patch does not apply" or a hunk error) means the target tree has drifted from where the patch was cut.

Fuzzy application with --3way

When a patch does not apply cleanly because the surrounding lines have moved, --3way falls back to Git's real merge machinery instead of failing outright. It needs the patch to record the blob identities it expects (the index lines that git format-patch and git diff include by default) and those blobs to exist locally:

bash
git apply --3way my.patch
git am --3way *.patch

Instead of giving up, --3way does a three-way merge and leaves you ordinary conflict markers to resolve, exactly like a branch merge. It is the first thing to reach for when a stock apply rejects a hunk against a tree that has moved on.

A note on the modern workflow

Most teams move work through pull requests on a shared remote now, so day to day you rarely cut a patch by hand. But patches still shine in the cases a PR cannot reach: moving a change between two repos that share no remote, sending a fix to a project you have no push access to, attaching a diff to a bug tracker, or the mailing-list workflow (git send-email) that large open-source projects like the kernel still run on. The commands have not changed in years, which is exactly why they are still the dependable fallback when there is no forge in the middle.

For getting yourself out of a mess rather than moving work between repos, see the guide to undoing things in Git. And if the commits you are about to export are noisy, squashing them first gives you cleaner patch files to hand over.

See also

Sources

Authoritative references this article was fact-checked against.

Tagsgitformat-patchgit amgit applypatch fileversion controlCLI

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts

How to Count Unique Matches with grep, sort, and uniq

The grep -o 'pattern' file | sort | uniq -c | sort -rn pipeline is the classic log-analysis one-liner. Why sort must come before uniq, how each stage works, worked examples for top IPs and status codes, the awk one-pass alternative for huge files, and the BSD vs GNU notes.

How to Exclude Matches with grep -v (Invert Match)

grep -v 'pattern' file prints every line that does NOT match. The flag reference, how to exclude multiple patterns, the strip-comments-and-blank-lines pipeline, the double-negative trap where -v of an OR becomes an AND of negations, and the macOS BSD vs GNU differences.