git am: Applying Email Patches Cleanly
AI generated
git
HEAD
Git · Patches · Workflow
git am: Applying Email Patches Cleanly
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.

10 min read Git Patches

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.

11. FAQ: git am

1What is the fundamental difference between git apply and git am?
git apply transfers only the line changes contained in a patch into the working tree, without creating a commit. git am reconstructs a full commit from it, including author, date and message.
2Which file format does git am expect?
The format produced by git format-patch: email headers with From, Date and Subject, followed by the commit message and a unified diff. Entire mbox files containing several such entries are also recognized automatically.
3How do I apply several patch files in a directory in the correct order?
git am accepts a directory path directly and applies every patch file it contains in alphabetical order, which combines well with the numbering produced by git format-patch.
4What happens if a patch does not apply cleanly?
git am stops at the affected patch and marks the conflicting spots in the working tree. After resolving them manually, git add followed by git am --continue resumes the process with the next patch.
5How do I skip a single problematic patch in a series?
git am --skip skips exactly the currently failing patch while the rest of the series continues to apply normally.
6How do I fully abort a running git am process?
git am --abort completely restores the state that existed before the very first patch of the current series was applied, including any commits already created during that run.
7What is the --3way option in git am for?
It enables a genuine three-way merge that also consults the base version referenced by the patch, letting significantly more patches apply automatically even when the surrounding code has drifted slightly.
8How do I add my own Signed-off-by line while applying someone else's patch?
The --signoff option makes git am automatically append an extra Signed-off-by line using the locally configured user data to the commit message.
9Can I apply an email straight from my mail client with git am?
Yes, as long as the message is saved as a plain text file in its original format. Mail clients that reformat the message as HTML often destroy the diff's line breaks in the process.
10When does git am beat the classic pull request workflow?
Mainly in decentralized projects without a central forge, for offline contributions, or when a single maintainer merges patches from various sources and needs the author and timing of the change reliably preserved.