git format-patch: Patch-Based Workflows Without Pull Requests
AI generated
git
HEAD
Git · Patches · Workflow
git format-patch: Workflows Without Pull Requests
commits as sendable patch files instead of merge requests

Not every Git project runs through a central forge with a pull request interface. git format-patch turns a series of commits into sendable patch files that recipients can reassemble into full commits with git am, with no GitHub, GitLab or other web interface involved at all. This article shows how to generate patch series, attach a cover letter, version them, and send them via git send-email, and when this workflow genuinely beats pull requests.

11 min read Git Patches

1. Core idea: commits as patch files instead of a pull request

A pull request is essentially a reference to two branches compared on a central server. That central instance simply does not exist in many decentrally organized projects, or it is deliberately avoided, for instance because a project has been organized through a mailing list for decades and nobody wants to give up the established rhythm of a well practiced contribution and review culture.

git format-patch removes this dependency on a central instance entirely: every commit gets turned into a self-contained, text-based file that carries all the information needed to become an identical commit again on the recipient's side. That file can travel over practically any channel, an email, a USB stick, or a simple file drop.

2. git format-patch: the structure of the generated files

Without further options, git format-patch produces one file per commit in the given range, named after a running number and a short description derived from the commit subject, such as 0001-fix-cache-invalidation.patch. Each of these files contains the full email headers with author and date, the complete commit message, and the associated diff in unified diff format.

The range can be specified either as a single commit reference, exporting every commit from that point to HEAD, or as an explicit two-dot range between two commits. The -o option sets the target directory for the generated files, which is useful for keeping several series cleanly separated from one another.


# Export every commit since diverging from main as patch files
git format-patch main --output-directory patches/

# Export exactly the last three commits
git format-patch -3

3. Generating a patch series with a cover letter

For several related commits, a short introductory description of the whole series is helpful before the recipient reads each individual patch in detail. The --cover-letter option automatically generates an extra file numbered 0000, which serves as a placeholder for such a summary and should be filled in by hand before sending, with motivation, an overview, and relevant background information.

Combined with -N, or the numbering that automatically kicks in once a series has two or more patches, every file additionally shows which part of the overall series it represents, for instance [PATCH 2/5] in the subject line, giving recipients an immediate sense of scope and position within the series.


# Generate a patch series including a cover letter file
git format-patch main --cover-letter --output-directory patches/

4. Sending patches by email with git send-email

Instead of manually sending generated patch files as attachments, which many mail clients render unusable through automatic reformatting, git send-email connects directly to a configured SMTP server and sends every patch file as its own, plain text email with correctly set headers, so the diffs it contains arrive unchanged on the recipient's end.

Configuration happens once via git config sendemail.smtpserver and the associated credentials, after which git send-email patches/*.patch is enough to send an entire series, including the cover letter, in the correct order and with correctly chained In-Reply-To headers, as a single coherent thread.


# Configure the SMTP server once
git config sendemail.smtpserver smtp.mironsoft.internal
git config sendemail.smtpserverport 587

# Send the entire series as a coherent email thread
git send-email --to=team@mironsoft.de patches/*.patch

5. Versioning patch series with v2, v3 and a reroll count

If an already sent series gets reworked after feedback, it usually is not resent without comment, but clearly marked as a new version. The --subject-prefix option lets you replace the default PATCH prefix in the subject line with custom text, such as PATCH v2, so everyone involved can immediately see which revision they are looking at.

Even more convenient is the -v option, which takes a version number directly and automatically adjusts both the prefix and the file names accordingly, without anyone having to construct a custom prefix string by hand. That keeps every revision of a series clearly traceable to the actual version it represents.


# Generate the second revision of a patch series, prefix and filenames adjusted automatically
git format-patch main -v2 --cover-letter --output-directory patches/

6. Comparing series with git range-diff

Anyone reviewing a second version of a patch series usually wants to know what actually changed content-wise since the first version, rather than reading each patch again from scratch. git range-diff compares two commit ranges by content for exactly this purpose and marks which patches stayed identical, which changed, and which were newly added.

For reviewers of a new version, that is the fastest way to focus purely on the actual changes relative to the previous version, instead of re-reviewing the entire series from the ground up with every revision.


# Compare the first and second version of the same series by content
git range-diff main feature-v1 feature-v2

7. Recipient side: checking and applying patches

On the recipient's side, a single file or a whole directory can usually be turned into full commits with the original author and original date using just git am. Before actually applying anything, a quick check with git apply --check is often worthwhile, since it only verifies whether a patch would apply cleanly without making any change yet.

For larger series, it is common practice to first apply the patches in a separate, local test branch, run the automated test suite there, and only then decide whether to merge into the main branch, quite similar to a pull request merge, just without the accompanying web interface.


# Check whether the patch would even apply cleanly before applying it
git apply --check 0001-fix-cache-invalidation.patch

# Apply in a dedicated test branch to test before merging
git checkout -b test-patch-series main
git am patches/*.patch

8. When the patch-based workflow beats pull requests

The patch-based workflow pays off especially where no single, central forge connects everyone involved, for instance in projects with several independent mirror repositories, contributions over unstable or restricted internet connections, or when contributors cannot or will not create an account with a particular provider for legal or organizational reasons.

For a typical, centrally organized Magento or web project running on GitLab with a fixed team, the effort is rarely justified, since pull requests offer inline comments, automatic CI runs, and a lower barrier to entry for new team members, none of which a pure email workflow readily replicates.

9. Practical pitfalls and a checklist for getting started

The most common source of trouble is a mail client that automatically converts plain text into HTML, altering line breaks or indentation of the diff along the way, which leaves the patch unable to apply cleanly on the recipient's end. Anyone unable to use a plain-text mail client or git send-email should therefore send patches as plain text attachments wherever possible, not embedded as formatted message text.

Another frequent pitfall is unclear ordering in multi-part series: without consistent numbering and a cover letter, recipients often cannot immediately tell in which order the patches need to be applied. Consistently using --cover-letter together with automatic numbering reliably avoids this problem from the start.

Aspect Pull request format-patch workflow Recommendation
Requires a central instance Yes, a forge like GitLab No, any transport channel works format-patch when no forge exists
Inline comments on the web Yes, built in No, replies only by email Pull request for web-based review
Automatic CI runs Usually built in Only with extra infrastructure Pull request when active CI is needed
Preparable fully offline Limited Yes, fully format-patch for unstable connectivity
Versioning a series Force push onto the same branch Dedicated v2, v3 files and threads format-patch for a traceable history

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

format-patch Workflow

Core principle

git format-patch turns commits into sendable text files that the recipient reassembles into commits with git am.

Series with context

--cover-letter produces an extra overview file explaining the motivation and scope of the whole series.

Sending

git send-email sends patches as correctly formatted plain text emails without destroying the diff's line breaks.

Comparing revisions

git range-diff shows by content what actually changed between two versions of a series.

11. FAQ: format-patch Workflow

1What exactly does git format-patch do?
It turns a series of commits into individual, sendable text files that carry all the information needed to become identical commits again on the recipient's end using git am.
2How do I generate an overview file for an entire patch series?
The --cover-letter option makes git format-patch generate an extra file numbered 0000, which should be filled in by hand before sending with motivation and an overview of the series.
3How do I send a patch series without mail clients corrupting the diff?
With git send-email, which connects directly to a configured SMTP server and sends every patch file as a correctly formatted plain text email without altering the line breaks.
4How do I mark a reworked version of an already sent series?
With the -v option followed by a version number, such as -v2, git format-patch automatically adjusts both the subject line prefix and the file names accordingly.
5How do I compare two versions of the same patch series by content?
With git range-diff, which compares two commit ranges by content and shows which patches stayed unchanged, which changed, and which were newly added.
6How do I apply a received patch series as the recipient?
Usually git am is enough, reconstructing full commits with the original author and date from the patch files. git apply --check beforehand can verify whether the patches would even apply cleanly.
7When is the patch-based workflow worth choosing over a classic pull request?
Mainly when no central forge connects everyone involved, over unstable internet connections, or when contributors cannot or will not use an account with a particular provider for organizational reasons.
8What is the most common source of trouble when sending patches by email?
Mail clients that automatically convert plain text into HTML, altering line breaks or indentation of the diff, which leaves the patch unable to apply cleanly for the recipient.
9How do I make sure recipients understand the correct order of a multi-part series?
By consistently using --cover-letter together with automatic numbering, which stamps every file and subject line with the total count and position within the series.
10Can patch-based workflows and pull requests coexist within the same project?
Yes, many teams use pull requests for everyday work and fall back on format-patch and git am only for external contributions without forge access or for offline situations.