To apply a patch in Git you use git apply for a plain diff or git am for a mailbox-format patch that carries commit metadata, and the security-conscious workflow is to preview the patch before applying, verify what it touched after, and never blindly apply a diff from an untrusted source. A patch is just a text description of changes, which makes it portable and easy to share, but also easy to slip something past a reviewer. This guide covers both commands and the safe habits around them.
Two kinds of patch, two commands
Git produces and consumes two related formats:
- A diff patch, created with
git diff > changes.patch, contains only the line changes. It has no author, date, or commit message. You apply it withgit apply. - A mailbox patch, created with
git format-patch, contains one file per commit including the full commit metadata and message. You apply it withgit am, which recreates the commits as commits.
Choosing the right command matters. If someone sends you the output of git format-patch and you run git apply, you lose the authorship and message. If you want to preserve the original commit history, use git am.
Applying a plain diff with git apply
Given a file feature.patch produced by git diff, the safe sequence is preview, then apply:
# 1. Preview: does it apply cleanly? (makes no changes)
git apply --check feature.patch
# 2. See what it would touch
git apply --stat feature.patch
# 3. Apply it to the working tree
git apply feature.patch
--check is the important habit. It tells you whether the patch applies against your current tree without modifying anything, so you catch conflicts before they leave a half-applied mess. --stat shows the files and line counts, which is your first sanity check that the patch touches only what you expect.
If you want the changes staged as well as applied, add --index. If you only want to update the index without touching the working tree, use --cached (useful in scripted pipelines).
Applying a commit patch with git am
For patches created by git format-patch, use git am to replay them as real commits:
# Preview the commit message and diffstat first
git apply --stat 0001-add-login-rate-limit.patch
# Apply, recreating the commit with original author and message
git am 0001-add-login-rate-limit.patch
# For a whole series of patch files
git am *.patch
git am preserves the author, date, and commit message, which is why it is the right tool for accepting contributions by email or moving commits between repositories that do not share a remote.
When a patch does not apply cleanly
Patches drift. If the target file changed since the patch was cut, the clean apply fails. You have a few options.
The -3 (three-way merge) flag lets Git fall back to a merge using the blob information in the patch, which produces standard conflict markers you resolve normally:
git apply -3 feature.patch
# or, for git am:
git am -3 0001-add-login-rate-limit.patch
If a git am run gets stuck mid-series, you resolve the conflicting files, git add them, then continue or abort:
git add resolved-file.js
git am --continue
# or bail out entirely and restore the pre-am state:
git am --abort
A softer fallback for stubborn diffs is git apply --reject, which applies the hunks it can and writes the failures to .rej files you patch by hand. Use it sparingly; a pile of .rej files is easy to apply incompletely.
Treat untrusted patches as untrusted code
A patch file is executable intent in text form. Applying one from a stranger is exactly as risky as merging their pull request, sometimes riskier, because a raw patch skips the review UI that would normally surface the diff. Before you apply anything you did not write:
- Read the whole patch. Open it in an editor and read every hunk, not just the diffstat. A malicious patch can bury a one-line change to a build script or CI file among dozens of legitimate hunks.
- Watch the high-risk files. Changes to
package.jsonscripts, CI workflow YAML,Makefiletargets,.git/hooks, or dependency manifests deserve extra scrutiny; those run code, not just ship it. - Use
--checkand--statfirst so you know the scope before anything lands. - Apply in a branch, never straight onto
main, so you can diff, test, and throw it away if it misbehaves:
git switch -c review/incoming-patch
git apply --check incoming.patch && git apply incoming.patch
git diff HEAD # review exactly what changed
A patch that quietly adds a dependency or edits a lockfile is a classic software supply chain vector. After applying anything that touches manifests, re-scan: an SCA tool such as Safeguard can catch a newly introduced vulnerable or malicious dependency that a manual diff read might miss. For how dependency changes turn into risk, see our software supply chain fundamentals.
Quick reference
git diff > my.patch # create a plain diff patch
git format-patch -1 HEAD # create a commit patch for the last commit
git apply --check my.patch # test without applying
git apply --stat my.patch # show affected files
git apply my.patch # apply working-tree changes
git am my.patch # apply as a commit with metadata
git apply -3 my.patch # apply with three-way merge on conflict
git am --abort # bail out of a failed am
FAQ
What is the difference between git apply and git am?
git apply applies a plain diff to your working tree without creating a commit or preserving author information. git am applies a mailbox-format patch from git format-patch, recreating the original commits with their author, date, and message intact. Use am when you want to preserve history.
How do I preview a patch before applying it in Git?
Run git apply --check patchfile to test whether it applies cleanly without changing anything, and git apply --stat patchfile to list the files and line counts it would touch. Always read the full patch in an editor before applying one you did not write.
How do I apply a patch that has conflicts?
Use the three-way merge flag: git apply -3 patchfile or git am -3 patchfile. This produces standard conflict markers you resolve normally. For git am, resolve the files, git add them, and run git am --continue, or git am --abort to back out entirely.
Is it safe to apply a patch from an untrusted source?
Treat it exactly like untrusted code. Read every hunk, pay special attention to changes in CI files, build scripts, git hooks, and dependency manifests, apply it in a throwaway branch, and re-scan dependencies afterward. A raw patch skips the pull-request review UI, so the scrutiny has to come from you.