Mastering git format-patch and git am: A Professional Email-Based Code Submission Workflow

Git tutorial - IT technology blog
Git tutorial - IT technology blog

Sending code via email: Old but never obsolete

If you’re used to clicking the “Create Pull Request” button on GitHub, sending code via email might sound a bit… manual. However, tech giants like the Linux Kernel, Git, and PostgreSQL have operated for decades using mailing lists and patch files. This isn’t stubbornness; it’s a choice driven by decentralization and efficiency.

I once worked on a financial project with extremely high security requirements. The Git server was located in an isolated network (air-gapped) with no internet connection. Pushing code to a central server was impossible. In that situation, git format-patch and git am became the only tools for the team to exchange code while preserving the full commit history and author information.

Quick Comparison: Pull Requests vs. Email Patches

Why do Open Source veterans still prefer email over modern platforms?

1. Pull Request (GitHub/GitLab)

  • Pros: Intuitive web interface, easy line-by-line code reviews, and built-in CI/CD integration.
  • Cons: Complete platform dependency (Vendor lock-in). You are forced to have an account and perform the somewhat cumbersome process of forking a repo.

2. Email Patch (format-patch & am)

  • Pros: Absolute decentralization. You only need the maintainer’s email address to send a contribution. Patch files are very lightweight (usually just a few KB) but contain full metadata like author, date, and commit message.
  • Cons: Steeper learning curve, requiring good command-line (CLI) skills to manage discussion threads.

3 Real-World Scenarios for Using Patches

Beyond the Linux Kernel, this duo is extremely useful in the following cases:

  1. Offline environments: When working in an internal network with blocked outbound connections or when the shared Git server is down.
  2. Sending quick fixes: Instead of creating a temporary branch on the server, you can just export a patch file and send it via Slack for a colleague to test in 30 seconds.
  3. Pure Open Source projects: Communities that prioritize lean operations and want to avoid dependency on big corporations like Microsoft (GitHub).

Step 1: Exporting patch files with git format-patch

Suppose you’ve just finished a feature on the feature-fix branch. To package the commits into files, use the following command:

# Export only the latest commit
git format-patch -1 HEAD

# Export all commits from the feature branch relative to main
git format-patch main..feature-fix

Git will generate files like 0001-commit-name.patch. The difference between this and a standard git diff is that it includes digital signatures, the author’s email, and the commit message.

Pro tip: If sending a series of multiple files, add the --cover-letter flag. This creates a 0000 file where you can write an overview summary of all changes, helping the maintainer grasp the context more easily.

git format-patch main -o outgoing/ --cover-letter

Step 2: Sending patches with git send-email

A common mistake is manually attaching the patch file to Gmail or Outlook. Email clients often automatically insert extra characters or change text formatting (like converting tabs to spaces). This will break the patch file structure, making it impossible for the recipient to apply.

The standard tool is git send-email. First, configure SMTP (e.g., with Gmail):

git config --global sendemail.smtpserver smtp.gmail.com
git config --global sendemail.smtpserverport 587
git config --global sendemail.smtpencryption tls
git config --global sendemail.smtpuser [email protected]

Then, send the patch with a single command:

git send-email --to="[email protected]" outgoing/*.patch

Step 3: Applying patches with git am

Upon receiving the patch file, the maintainer will use the git am (Apply Mail) command to integrate the code into the project.

# Check patch integrity before applying
git apply --check 0001-fix-bug-logic.patch

# Apply the patch and automatically create the corresponding commit
git am 0001-fix-bug-logic.patch

After running the command, your commit will appear in the project’s Git history with all original information, just as if you had committed directly on their machine.

How to Handle Conflicts?

If the original code has changed too much, git am will fail. Don’t worry; use the --3way flag to let Git attempt a 3-way merge, minimizing the rate of manual errors.

git am --3way 0001-fix-bug-logic.patch

If conflicts still exist, Git will stop for you to fix them manually. Once finished, simply run:

git add .
git am --continue

Conclusion

Initially, this process might seem more complicated than clicking buttons on a UI. However, once mastered, you’ll find it offers immense freedom. Everything is plain text. You don’t have to worry about server downtime or GitHub’s interface changing.

One final note: When sending a patch, write very clear commit messages. In the world of email, the commit message is the only documentation that helps others understand your thought process. Good luck with your implementation!

Share: