git format-patch: Email-Ready Patches in CI
git format-patch <range> writes one numbered .patch file per commit (with full author and message), the mailbox format that git am replays exactly.
When a pipeline moves commits between repos or stores them as artifacts, format-patch produces self-contained patch files that preserve authorship and message, unlike a plain git diff. The range and --stdout forms are the ones CI uses.
What it does
git format-patch generates a patch file per commit in mbox format, including author, date, subject, body, and the diff, so git am can recreate the commits faithfully. You select commits by range (origin/main..HEAD), by count (-3 for the last three), or stream them to one stream with --stdout.
Common usage
# one file per commit since origin/main
git format-patch origin/main..HEAD
# the last 3 commits
git format-patch -3
# a single combined stream (pipe into git am)
git format-patch origin/main..HEAD --stdout > series.patch
# into a directory, with a cover letter
git format-patch -o patches/ --cover-letter origin/main..HEADOptions
| Flag | What it does |
|---|---|
| <since>..<until> | Format commits in the range |
| -<n> | Format the last n commits |
| --stdout | Write all patches to stdout as one stream |
| -o <dir> | Write the .patch files into a directory |
| --cover-letter | Add a 0000 cover letter for the series |
| --signoff | Add a Signed-off-by trailer |
In CI
format-patch against a base needs that base present, so a shallow clone can silently produce too few patches or none; fetch enough history. The output of format-patch is exactly what git am consumes, so the round trip format-patch | git am preserves SHAs of content and authorship. Use --stdout to keep it to one artifact.
Common errors in CI
No files produced usually means the range was empty (base equals HEAD, or the base ref is missing on a shallow clone), not an error. "fatal: ambiguous argument 'origin/main..HEAD'" means the base ref was not fetched. On git am later, "patch does not apply" means the target tree diverged from where the patches were generated.