reconstructing commits, not just diffs, from patch files
Where git apply merely transfers a diff into the working tree, git am reconstructs a full commit, including author, date and commit message, from a patch file. That makes git am the central tool for patch-based workflows, the kind still standard in Linux kernel development, in Git itself, and across many mailing-list-driven open source projects. This article shows how to apply single patches and entire series cleanly, how to resolve conflicts along the way, and when git am is worth choosing over a classic pull request merge.
Table of Contents
- 1. What distinguishes git am from git apply
- 2. The structure of an email patch that git am expects
- 3. Applying a single patch
- 4. Applying an entire patch series from an mbox file
- 5. Resolving conflicts during git am
- 6. Three-way merge as a fallback with --3way
- 7. Adding a signoff and metadata while applying
- 8. Extracting and preparing patches from a mail client
- 9. Practical context: when git am beats the pull request workflow
- 10. Summary
- 11. FAQ
1. What distinguishes git am from git apply
git apply takes a patch file and transfers only the line changes it contains into the working tree, without creating a commit at all. That makes it well suited for quickly checking whether a patch even applies cleanly, or for trying out changes locally without touching the history.
git am goes a decisive step further: it expects a patch file in the format produced by git format-patch, complete with email headers for author, date and subject line, and turns that into a full, self-contained commit. That means the recipient keeps not just the code difference but the entire provenance of the change, exactly as it existed for the original author.
# Apply only the diff, without creating a commit
git apply 0001-fix-cache-invalidation.patch
# Reconstruct a full commit including author, date and message
git am 0001-fix-cache-invalidation.patch
2. The structure of an email patch that git am expects
A patch file in the format expected by git am starts with classic email header lines such as From, Date and Subject, followed by the actual commit message and finally the diff itself in unified diff format. That exact format is what git format-patch automatically produces from every commit, which is why the two commands function as a natural counterpart pair.
The subject line matters here: it usually follows the pattern [PATCH] followed by the actual commit subject line, and git am uses precisely that part to reconstruct the later commit message. If this format is missing or the file is not a valid patch, git am immediately reports an error instead of silently applying an incomplete change.
# Beginning of a typical file generated by git format-patch
From 3f2c1a9b1e4d6a7c8b9e0f1a2b3c4d5e6f7a8b9c Mon Sep 17 00:00:00 2001
From: Jane Developer <jane@example.com>
Date: Mon, 3 Aug 2026 10:15:00 +0200
Subject: [PATCH] Fix cache invalidation on product save
3. Applying a single patch
The simplest case is a single patch as a local file: git am path/to/patch reads the file, checks whether it applies cleanly to the current state of the working tree, and on success immediately creates a new commit carrying the original metadata. The working tree needs to be clean for this, pending uncommitted changes block the process.
If a directory is given instead of a file path, git am automatically applies every patch file it contains in alphabetical order, which combines nicely with the numbering produced by git format-patch, such as 0001-, 0002-, to apply an entire series in the correct order.
# Apply a single patch
git am 0001-fix-cache-invalidation.patch
# Apply every patch file in a directory, in alphabetical order
git am patches/
4. Applying an entire patch series from an mbox file
Many email clients and mailing list archives allow exporting an entire thread as a single mbox file, which contains several emails in sequence within a shared text format. git am automatically recognizes this format, internally splits the file into individual patches, and applies them one after another, without anyone having to break the patches into separate files by hand beforehand.
This is especially handy for patch series coming from projects that operate purely over mailing lists: the whole thread gets downloaded as a single mbox file, and one invocation of git am applies the entire series in its original order.
# Apply an entire mbox file containing several patches at once
git am full-patch-series.mbox
5. Resolving conflicts during git am
If a patch does not apply cleanly to the current state of the working tree, git am stops at the affected patch and marks the conflicting spots in the working tree exactly as it would for a regular merge conflict. After resolving the conflicts by hand, the affected files get staged with git add, and git am --continue resumes the process with the next patch of the series.
If a single patch cannot be reasonably resolved, for instance because it has since been fully superseded by another change, git am --skip skips exactly that one patch and moves on to the next. If the entire process should be reversed instead, git am --abort fully restores the original state that existed before the first patch of the series was applied.
# Resolve the conflict manually, then continue
git add path/to/conflicted-file.php
git am --continue
# Skip this one patch and move on to the next
git am --skip
# Abort the whole process and restore the starting state
git am --abort
6. Three-way merge as a fallback with --3way
By default, git am tries to apply a patch purely by text, based on the line context contained in the patch. That fails more often than one might expect once the surrounding code has drifted even slightly since the patch was created, even when the actual change would still fit in perfectly well content-wise.
The --3way option instead triggers a genuine three-way merge, in which Git additionally consults the base version of the file referenced by the patch, provided that version is available in the local repository. That lets significantly more patches apply automatically, even when the surrounding context has shifted slightly, while real content conflicts still get flagged clearly as such.
# Enable a three-way merge, much more robust against slightly shifted context
git am --3way 0001-fix-cache-invalidation.patch
7. Adding a signoff and metadata while applying
In many open source projects, particularly in the kernel world, the contribution process requires a Signed-off-by line in every commit message as a formal confirmation that the contribution may be submitted under the project's license. Anyone applying someone else's patch with git am who also wants to add their own signoff can use the --signoff option, which automatically appends an extra Signed-off-by line using the locally configured user data.
This matters most when patches get forwarded through an additional intermediate step, for instance when a maintainer picks up a patch from a mailing list and forwards it to the project with their own signoff attached, without altering the original author or their commit message.
# Append an extra Signed-off-by line while applying
git am --signoff 0001-fix-cache-invalidation.patch
8. Extracting and preparing patches from a mail client
For receiving a single patch by email, it is usually enough to save the message in its raw format as an .eml or plain text file and hand it directly to git am, as long as the mail client has not additionally reformatted the message as HTML and thereby destroyed the diff's line breaks. Precisely that risk is the main reason many projects explicitly recommend plain-text-only mail clients or git send-email for sending patches.
If several related patches arrive as separate emails, they can either be saved one by one and applied individually with git am, or exported together as a single thread into one mbox file, which is usually the much faster path for larger series.
9. Practical context: when git am beats the pull request workflow
For projects built around a central forge like GitLab or GitHub, the classic pull request workflow usually remains the more pragmatic choice, since it brings inline comments, a web interface and automatic CI integration that git am does not offer out of the box. The patch-based workflow shows its strengths precisely where that central infrastructure is missing or deliberately avoided.
For decentralized projects, offline contributions, or environments where a single maintainer merges patches from a wide range of sources, git am remains the more robust tool, because it reliably preserves author, timestamp and commit message of the original change, regardless of the actual channel through which the patch was transferred.
| Aspect | git apply | git am | Recommendation |
|---|---|---|---|
| Creates a commit | No, working tree change only | Yes, with original metadata | git am for full history |
| Preserves author and date | No | Yes | git am for third-party contributions |
| Handles full mbox series | No | Yes, split automatically | git am for patch series |
| Conflict handling | Manual, no built-in workflow | --continue, --skip, --abort | git am for multiple patches |
| Suited to quick experimentation | Yes, without changing commit history | Less so, creates commits immediately | git apply for pure testing |
Mironsoft
Git workflows, branching strategies, and CI hooks
Chaotic Git history and unclear branching rules across the team?
We set up clean Git workflows, clarify branching strategies for the team, and automate quality checks via Git hooks and CI pipelines so the history stays traceable.
Workflow Audit
Review the existing branching strategy and merge practice for weak spots.
Hook Automation
Set up pre-commit and pre-push hooks for linting, tests, and commit conventions.
Team Training
Teach rebase, cherry-pick, and conflict resolution hands-on across the team.
10. Summary
git am
Core difference
git apply transfers only the diff, git am turns it into a full commit with author, date and message.
Expected format
A file generated by git format-patch with email headers, commit message and unified diff, or an entire mbox file.
Conflict handling
git add plus git am --continue after manual resolution, --skip to skip, --abort to fully reset.
More robust fallback
The --3way option uses a genuine three-way merge when needed and rescues more patches automatically.