A patch often arrives at an awkward moment: the fix is ready, but the other repository cannot pull your branch, or the reviewer needs a change that can travel through email, a ticket, or an isolated network. You are not merely moving lines. You are handing someone a small piece of project history and hoping it lands cleanly.

For one ordinary, non-merge commit, git format-patch -1 <commit> is the dependable choice. It writes an email-style patch containing the commit message, author identity, and diff. The -1 matters: it limits the output to the named commit instead of selecting a wider history range.

Look at the commit before you package it

Terminalbash
git show --stat --summary <commit>
git show --format=fuller --no-ext-diff <commit>

This is the moment to catch the wrong hash

  • Replace <commit> with a commit ID, tag, or other revision that resolves to exactly the commit you intend to share.

  • --stat --summary gives a compact view of affected paths, modes, renames, and commit metadata.

  • The second command shows the patch while --no-ext-diff prevents a configured external diff driver from changing what you review.

  • Search the diff for credentials, tokens, private hostnames, generated files, and customer data. A patch is plain text and is easy to forward.

  • These commands only inspect repository objects; they do not modify the working tree or history.

Put exactly one commit in a deliberate directory

Terminalbash
mkdir -p outgoing-patches
git format-patch -1 <commit> -o outgoing-patches
outgoing-patches/0001-Describe-the-change.patch

The filename is helpful, but the commit is the source of truth

  • -1 is short for --max-count=1; it selects the named commit only.

  • -o outgoing-patches controls the destination directory. Git creates a numbered filename from the commit subject.

  • The displayed filename is illustrative because the real subject determines it.

  • format-patch includes the commit message, author information, and a diff suitable for git am.

  • This exact one-commit behavior and output naming were reproduced with Git 2.43.0 in a disposable two-commit repository.

When a pipeline truly needs standard output

Terminalbash
git format-patch -1 <commit> --stdout > change.patch

Risk level: caution. Review the command before running it.

Redirection changes who owns the filename

  • --stdout sends patch content to standard output instead of creating Git’s numbered file.

  • The shell truncates change.patch before Git writes it. Choose a new path or inspect an existing one first.

  • This form is useful for compression, encryption, or a transport pipeline, but -o is clearer for ordinary local files.

  • Do not paste terminal diagnostics into the redirected stream; a mail patch must remain byte-for-byte parseable.

Inspect the parcel from the receiver’s side

Terminalbash
git apply --stat outgoing-patches/0001-Describe-the-change.patch
git apply --check outgoing-patches/0001-Describe-the-change.patch
 notes.txt | 1 +
 1 file changed, 1 insertion(+)

A successful check is evidence, not a reservation

  • git apply --stat reports the patch summary without applying changes.

  • git apply --check tests the diff against the current files and exits nonzero when context or paths do not match.

  • The shown statistic and a successful check were produced locally on the parent of a two-commit test repository using Git 2.43.0.

  • Run the check again immediately before applying if the branch moves; another edit can invalidate an earlier result.

  • git apply --check checks the diff, not the authorship, commit message, build, tests, or safety of the code.

Recreate the commit with git am

Terminalbash
git status --short
git switch -c receive-fix
git am --3way outgoing-patches/0001-Describe-the-change.patch
Applying: Describe the change

Risk level: caution. Review the command before running it.

Why this is different from applying a plain diff

  • Start from the intended base and a clean working tree; git status --short should show nothing you might confuse with patch changes.

  • git switch -c creates a reviewable topic branch without rewriting the source branch.

  • git am reads mail headers and creates a new commit with the patch’s author and message; the committer and commit object ID will normally differ.

  • --3way lets Git attempt a three-way merge when the patch records usable blob identities and direct application fails.

  • The shown flow was executed with Git 2.43.0 in a disposable receiver repository; it preserved the test author and subject while creating the receiving commit.

If a conflict interrupts the handoff

Terminalbash
git am --show-current-patch=diff
# Resolve the conflicted files, then stage only the resolutions.
git add <resolved-paths>
git am --continue

Risk level: caution. Review the command before running it.

Keep the resolution narrow and observable

  • --show-current-patch=diff displays the diff for the mail message currently being applied.

  • Replace <resolved-paths> with reviewed paths; avoid git add . when unrelated files may be present.

  • git am --continue creates the commit after conflicts are resolved and indexed.

  • Run the project’s relevant tests before publishing the resulting branch.

  • These are documented recovery commands; no conflict was manufactured for the local verification run.

Abandon the attempt without abandoning your branch

Terminalbash
git am --abort

Risk level: caution. Review the command before running it.

Abort is for the active am session

  • Use this when the conflict is wrong for the target branch or needs a fresh patch from the sender.

  • --abort stops the entire current am operation rather than skipping only one mail message.

  • Inspect git status afterward and retain any unrelated work according to your team’s workflow.

  • This recovery behavior is validated against the official git am documentation rather than exercised against valuable project history.

Use a plain diff when history is deliberately out of scope

Terminalbash
git diff --binary <commit>^ <commit> > content-only.patch
git apply --check content-only.patch
git apply content-only.patch

This moves content, not the original commit envelope

  • <commit>^ names the first parent, so the diff describes the transition from that parent to the commit.

  • --binary includes binary changes in a form git apply can consume; it also preserves full-index information.

  • git apply changes the working tree without creating a commit or preserving the original message and author.

  • The parent expression fails for a root commit and is ambiguous as a storytelling device for merges.

  • Review and commit the resulting changes separately if a content-only handoff is what the receiver requested.

Root commits need an explicit boundary

Terminalbash
root_commit=$(git rev-list --max-parents=0 <commit>)
git format-patch --root -1 "$root_commit" -o outgoing-patches
outgoing-patches/0001-Initial-commit.patch

Root is a special case because there is no parent

  • git rev-list --max-parents=0 finds root commits reachable from the supplied revision; unusual histories can have more than one, so inspect the result.

  • --root allows the root commit to be emitted as a patch against an empty tree.

  • -1 still limits the selection to one commit.

  • This syntax produced one root-commit patch with Git 2.43.0 in the local disposable repository.

  • Do not use command substitution blindly when multiple roots can be returned; select and verify the intended object first.

A series is ordered history, not a bag of files

Terminalbash
git format-patch <base>..<tip> -o outgoing-patches

Read the two dots as a selection rule

  • <base>..<tip> selects commits reachable from tip that are not reachable from base.

  • Git numbers the resulting files in the order they should normally be fed to git am.

  • The base commit itself is excluded. Confirm the set with git log --oneline <base>..<tip> before sharing.

  • Merge commits are normally omitted because an email patch represents a change relative to one parent, not the topology and conflict decisions of a merge.

  • For a branch already visible to the receiver, sharing the ref and using cherry-pick or merging may communicate intent better than flattening it into patches.

Things a clean-looking patch can still miss

  • Merge commits: format-patch does not preserve merge topology or conflict-resolution intent. Share the branch, cherry-pick an appropriate non-merge commit, or choose a bundle.

  • Binary files: format-patch supports Git binary patches, but review size and receiver limits. A plain git diff needs --binary for an applicable binary representation.

  • Renames and file modes: Git records content and mode changes; rename reporting is similarity detection, so inspect the resulting patch rather than relying on a label.

  • Submodules: the patch changes the recorded gitlink commit, not the nested repository’s objects. The receiver must obtain those objects separately.

  • Git LFS: a normal patch carries the small pointer file, not the large object. The receiver also needs access to LFS storage.

  • Untracked files: commits do not contain them, so format-patch cannot include them. Add and commit intended files before generating the patch.

  • Whitespace damage: chat tools and rich-text email clients can wrap or alter a patch. Transfer it as a file and use git am whitespace diagnostics when appropriate.

  • Wrong base: git apply --check or git am --3way may expose the mismatch, but neither can prove the resulting behavior is correct. Build and test on the receiving branch.

The handoff I would send to a teammate

  1. Name the commit and intended base branch in the message.

  2. Attach the reviewed .patch file instead of pasting its contents into formatted chat.

  3. Say whether the receiver should use git am to preserve commit metadata or git apply for content only.

  4. Include the tests you ran and any required submodule or LFS access.

  5. Keep the source branch until the receiver confirms the patch applied and behaved correctly.

That small amount of context is kindness disguised as process. The receiver should not have to reverse-engineer whether your patch is one commit, one file, or one half of a larger change.

Nearby Git work

Git documentation used for validation