Home / Alt manpages / git-format-patch(1)

  • git-format-patch(1)
  • User command
  • linux

Build and Check a Git Patch Series with format-patch

You will turn a known Git revision range into numbered patch files that a reviewer can inspect or a recipient can apply with git am. The workflow also checks the range before writing files, so a single-commit argument does not quietly mean what you expected it to mean. Allow about fifteen minutes. You need Git and a repository with at least two commits; no elevated privileges are required.

The examples here use Git 2.43.0 from Ubuntu package git-man 1:2.43.0-1ubuntu7.3. Git configuration can change defaults such as the output directory, subject prefix, threading and sign-off behaviour, so the explicit options below are the useful contract to review.

1. Check the repository and choose the range

First confirm that you are in the repository you mean to publish. This is read-only:

$ git rev-parse --show-toplevel
/path/to/project
$ git status --short
$ git log --oneline --decorate -n 5

For a series that exists on your current branch but not on origin/main, use origin/main..HEAD. The two-dot range means commits reachable from HEAD but not from origin/main. Preview exactly what that selects:

$ git log --oneline origin/main..HEAD
7c91f40 Add input validation
3a8e1b2 Document the configuration file
$ git diff --stat origin/main..HEAD
 config/app.conf | 8 ++++++++
 1 file changed, 8 insertions(+)

Checkpoint: if this log contains an unrelated commit, stop and correct the range before generating anything. A clean working tree is not required for format-patch, but checking it prevents confusion about changes that are not committed and therefore cannot appear in the patch series.

2. Write the series to a new directory

Create an output directory and pass it explicitly. Git creates missing directory components for --output-directory; using a new directory keeps generated files separate from source files.

$ mkdir -p /tmp/project-patches-v1
$ git format-patch --output-directory /tmp/project-patches-v1 origin/main..HEAD
/tmp/project-patches-v1/0001-Document-the-configuration-file.patch
/tmp/project-patches-v1/0002-Add-input-validation.patch

Each non-merge commit becomes one mbox-style message. The file begins with a From <commit> marker, contains the author and subject, then the commit message and a three-dash separator before the diff. Merge commits are omitted, because a simple patch does not carry enough information to recreate a merge.

Do not use shell redirection to create these files. git format-patch chooses safe names from the commit subjects and reports each path. If a directory already contains valuable patches, choose another directory. The command does not alter Git history, but rerunning it can overwrite files with the same names.

3. Inspect the first patch before sending it

Read the headers and the separator, then compare the diff with the preview from step 1:

$ sed -n '1,30p' /tmp/project-patches-v1/0001-*.patch
From 3a8e1b2... Mon Sep 17 00:00:00 2001
From: Developer Name <[email protected]>
Subject: [PATCH] Document the configuration file

...commit message...
---
 ... files changed ...
diff --git a/config/app.conf b/config/app.conf

The fixed date in the first From line is a format marker, not the commit date. The subject normally comes from the first paragraph of the commit message. For multiple patches Git uses subjects such as [PATCH 1/2]; for one patch it normally uses [PATCH].

Use git apply --check when you want to test the diff mechanics without making a commit:

$ git apply --check /tmp/project-patches-v1/0001-Document-the-configuration-file.patch
$ printf 'check status: %s\n' "$?"
check status: 0

This checks application to the current files, not whether the selected history or the commit message is appropriate. Keep the original patch directory until the recipient confirms the series.

4. Make numbering and output unambiguous

Use --numbered-files when another tool expects names containing only sequence numbers:

$ mkdir -p /tmp/project-patches-v1-numbered
$ git format-patch --numbered-files --output-directory /tmp/project-patches-v1-numbered origin/main..HEAD
/tmp/project-patches-v1-numbered/1
/tmp/project-patches-v1-numbered/2

For a one-commit fix, -1 HEAD means that exact commit. By contrast, a lone commit name without -1 is interpreted as a <since> boundary: Git formats commits leading up to it. If you intend to format a range from the beginning of history, add --root.

For a pipeline or a mail tool that reads standard input, use --stdout. The output is one mbox stream rather than separate files:

$ git format-patch --stdout origin/main..HEAD > /tmp/project-series.mbox
$ file /tmp/project-series.mbox
/tmp/project-series.mbox: Mailbox file, ASCII text

Redirection truncates an existing destination before Git runs. Choose a new path, or write to a temporary file and inspect it before replacing a previous mailbox. If the command fails, the old file is not recoverable unless you made a backup.

5. Prepare a reviewable series

Add a cover letter for a multi-commit series when reviewers need context beyond the individual commit messages:

$ git format-patch --cover-letter --subject-prefix='PATCH project' \
    --output-directory /tmp/project-patches-v1 origin/main..HEAD
/tmp/project-patches-v1/0000-cover-letter.patch
/tmp/project-patches-v1/0001-Document-the-configuration-file.patch
/tmp/project-patches-v1/0002-Add-input-validation.patch

The cover letter contains the branch description, a shortlog and an overall diffstat. Edit its description before sending. The subject prefix becomes [PATCH project], which helps a shared mailing list distinguish this series from patches for other projects.

For a second revision, use --reroll-count=2, which adds v2 to names and subjects. If you are updating a series that reviewers have already seen, a range-diff is often more useful than asking them to rediscover every change:

$ git format-patch --cover-letter --reroll-count=2 \
    --range-diff=feature-v1 --output-directory /tmp/project-patches-v2 \
    origin/main..HEAD

feature-v1 must name the tip of the earlier series and share its base with the new series. Check the cover letter: the range-diff is reviewer commentary, not part of the commit messages.

6. Set only the mail metadata you intend

Use --to and --cc to add recipient headers. They do not send mail:

$ git format-patch [email protected] \
    [email protected] --output-directory /tmp/project-patches-v1 \
    origin/main..HEAD

These options may also be configured under [format], alongside subjectPrefix, suffix, numbered, signOff, outputDirectory and coverLetter. Inspect inherited configuration before trusting a short command:

$ git config --show-origin --get-regexp '^format\.'
file:/home/me/.gitconfig format.subjectPrefix PATCH project

A repository or global setting can add headers or change the output location. An explicit --output-directory takes precedence over format.outputDirectory. Treat --signoff as a statement you are authorised to make: it adds your committer identity as a Signed-off-by trailer and is not a cryptographic signature.

7. Apply a received series safely

On a disposable test branch, inspect the files and then use git am to turn the mbox messages back into commits:

$ git switch -c review-project-series origin/main
$ git am --3way /tmp/project-patches-v1/*.patch
Applying: Document the configuration file
Applying: Add input validation

Do this only after checking the sender and the patch content. Applying a patch changes the repository history and working tree. If an application stops at a conflict, inspect the files, resolve them, stage the resolutions and run git am --continue. To abandon the in-progress application and return to the pre-git am state, run:

$ git am --abort

Do not run git am --abort after resolving a conflict unless you really want to discard that in-progress application. It does not delete the original patch files, but it does remove the temporary application state and restores the branch.

Done means

  • git log origin/main..HEAD showed exactly the commits you meant to publish.
  • Each selected non-merge commit has a numbered patch in a deliberate output directory.
  • The patch headers, subjects, three-dash separators and diffs were inspected.
  • Any cover letter, recipients, subject prefix, sign-off and reroll number reflect an intentional choice.
  • The generated files are retained until the recipient confirms that the series applies cleanly.