Skip to content
masterclass Buddy

Git · Command

git format-patch

git format-patch turns a range of commits into email-ready patch files, one per non-merge commit, in UNIX mbox style. It keeps the author, date and commit message, so the recipient can rebuild the same commits with git am or send them with git send-email.

Last updated

How it works

You pick the commits in one of two ways. A single commit <since> means every commit on the current branch that is not reachable from it, and a revision range means exactly the commits in that range. Each patch has three parts: a header (a From <sha> line with a fixed fake date, plus author, date and a Subject taken from the commit title), the rest of the commit message, and a --- separator followed by the diffstat and diff against the parent. Files are named NNNN-title.patch and go in the current directory, or in the directory given by -o. With --stdout everything is written to standard output as one mbox stream.

Syntax

git format-patch [-k] [(-o|--output-directory) <dir> | --stdout] [--thread[=<style>]] [-s] [-n | -N] [--cover-letter] [--subject-prefix=<prefix>] [--rfc[=<rfc>]] [-v <n>] [--to=<email>] [--cc=<email>] [--interdiff=<previous>] [--range-diff=<previous>] [--base=<commit>] [<common-diff-options>] [<since> | <revision-range>]

Parameters

NameTypeDescription
<since> | <revision-range>revisionWhich commits to format. A single commit means everything on the current branch since that commit. A range such as A..B means the commits in that range.
-<n>integerFormat only the topmost n commits. For example, -1 <commit> formats just that one commit.
-o, --output-directory=<dir>pathDirectory to write the patch files to. It overrides format.outputDirectory, and missing directories are created.
--stdoutflagWrite all patches to standard output in mbox format instead of one file per commit.
--cover-letterflagAlso write a 0000 cover-letter file with the branch description, the commit list and the overall diffstat.
-v, --reroll-count=<n>stringMarks the series as iteration n. It adds vN- to the filenames and appends vN to the subject prefix.
--subject-prefix=<prefix> / --rfc[=<rfc>]stringUse your own subject prefix instead of [PATCH], or put RFC (or another word) in front of it.
--thread[=shallow|deep]stringAdds Message-ID, In-Reply-To and References headers so the mails form a thread. Off by default.
--base[=<commit>|auto]revisionRecords which base tree the series applies on top of.
-s, --signoffflagAdds a Signed-off-by trailer using your committer identity.

Returns

Writes one .patch file per selected non-merge commit, plus an optional cover letter, and prints the generated filenames to standard output. With --stdout it writes one mbox stream to standard output instead.

Key points

  • Patch numbers in the subject are automatic: a single patch gets plain [PATCH], while a series gets [PATCH n/m]. Use -n to force numbering on a single patch, or -N to turn it off.
  • --cover-letter gives you a 0000 introduction mail to edit before sending. It is already filled in with a summary of the series.
  • When you send a new version of a series, --range-diff or --interdiff adds a comparison with the old version to the cover letter (or to the single patch), which helps reviewers.
  • --base adds base-commit information so the recipient knows which commit the series should be applied on. --base=auto picks that commit automatically.
  • --ignore-if-in-upstream drops commits whose change has already been applied upstream, by comparing patch content rather than commit IDs.
  • Commits that change nothing are skipped unless you pass --always.
  • --notes puts git notes after the --- line, so per-commit reviewer comments can be kept in notes and reused from one version of the series to the next.

Common mistakes

  • A single commit argument is read as <since>, not as 'just this commit'. git format-patch abc123 formats everything after abc123. To format only that commit use -1 abc123, and to format all history up to it use --root.
  • git send-email threads mails itself. If you also use --thread in format-patch, turn off threading in send-email, or the threads will be wrong.
  • Don't use --from when the output goes to git send-email, because send-email already does that sender rewriting for you.
  • --no-binary swaps binary diffs for a short notice, so the patches can be reviewed but not applied.

Example: Prepare a patch series, reroll it, and round-trip a single patch

#!/usr/bin/env bash
set -euo pipefail

# v1: every commit on the current branch that is not in origin/main
git format-patch -o outgoing/ --cover-letter --base=origin/main origin/main
# -> outgoing/0000-cover-letter.patch, 0001-....patch, ...

# v2 after review: compare with the old tip, kept as branch topic-v1
git format-patch -v2 -o outgoing/ --cover-letter \
  --range-diff=topic-v1 --base=origin/main origin/main
# -> outgoing/v2-0000-cover-letter.patch, v2-0001-....patch, ...

# Only the latest commit, as an mbox stream
git format-patch -1 --stdout HEAD > latest.patch

# On another clone: recreate the commit with author and message intact
git am latest.patch

The script makes a first and a second version of a series (the second includes a range-diff), then exports one commit and rebuilds it elsewhere with git am.

When to use it

Mailing-list contributions

Projects such as Git or the Linux kernel take changes by email. You format your topic branch with a cover letter, -s for sign-off and --to/--cc, then send it with git send-email.

Moving commits without a shared remote

Two repositories can't reach each other over the network. You copy patch files across, and git am recreates the commits with their original authors and messages.

Reviewing a reworked series

After review feedback you rebase and send v3 with -v3 and --range-diff=<old-tip>, so reviewers only need to look at what changed.

Archiving or auditing a change set

You export a release branch's commits to numbered .patch files, for example with --numbered-files or --suffix=.txt, to attach to a ticket or keep for compliance.

Interview questions

QWhy use git format-patch instead of git diff > change.patch to share commits?

git diff gives you only the code changes. format-patch writes one mail-style file per commit that also holds the author, the author date and the full commit message, with the diff after a --- line. git am can then rebuild the exact commits, keeping authorship and history, instead of leaving uncommitted changes.

Follow-up: What happens to merge commits in the range? They are skipped, because format-patch only handles non-merge commits. A history that contains merges has to be made linear, or shared another way such as git bundle or a pull request.

QHow would you send version 3 of a patch series so reviewers can follow what changed?

Run format-patch with -v3, which puts v3- in front of the filenames and gives subjects like [PATCH v3 n/m]. Add --cover-letter and --range-diff=<v2-tip> or --interdiff=<v2-tip> so the comparison with v2 is included. You can also use --in-reply-to=<message-id> so v3 stays in the earlier thread.

Follow-up: Why does --creation-factor default to 999 here and not 60 as in git range-diff? Because rerolls are expected to resemble the old series, the higher value makes the tool more willing to pair old and new commits.

QEvery patch starts with 'From <sha> Mon Sep 17 00:00:00 2001'. What is that date for?

It is a fixed, made-up mbox separator date. It makes the file look like a UNIX mailbox while letting tools such as file(1) tell that it came from format-patch and is not a real mailbox. The real author date is in the Date: header.

Follow-up: How can you hide the commit hash on that line, for example to get reproducible output? Pass --zero-commit, which writes an all-zero hash in place of the real one.

  • git am
  • git send-email
  • git apply
  • git range-diff
  • git request-pull
  • git notes
  • git diff
  • gitrevisions

Source: Git - git-format-patch Documentation. Checked 2026-11-02.