git create patch means turning a set of code changes into a portable file — a git patch file — that someone else can apply to their own working tree without cloning your repo, seeing your branch, or touching your commit history at all. Two commands cover the whole job: redirect git diff to a file for a quick git diff patch, or run git format-patch when you want each commit to carry its own author, date, and message. This guide covers both ways to generate a patch file — the ones git developers actually reach for — how to apply a git patch with git apply or git am, how to grab a github patch straight off a pull request URL, and — the part most patch tutorials skip entirely — how to actually read an untrusted patch before you let it touch your working tree. For the diff format itself, line by line, see the guide to unified diff format; this one is about turning that format into a file you can generate, share, inspect, and apply.

The Fast Answer: Creating a Git Patch in Two Commands

To create a patch, redirect a diff to a file; to apply it, hand that file to git apply. That's the entire operation when you just need to move a change from one working tree to another.

# Create a patch from whatever's changed in your working tree
git diff > my-changes.patch

# Apply it — on this machine, another clone, or someone else's
git apply my-changes.patch

Whatever you call the process — git patch, git create patch, git generate patch, git make patch, or on GitHub specifically github generate patch — the mechanics reduce to two steps: make the patch, then apply it. How to apply a git patch you didn't create yourself is exactly as short, once you have the file in hand and you've confirmed it's safe (covered in read the patch before you apply it further down):

# A .patch file downloaded from a GitHub PR, applied straight in
curl -L https://github.com/owner/repo/pull/123.patch | git am

A git diff patch and a format-patch patch look almost identical on the inside — both are unified diffs — but they carry different metadata and get applied with different commands. Create patch file git, apply github patch, github patch file — these phrasings all point at the same handful of commands; the sections below work through each one in full, then cover generating, reading, applying, reversing, and troubleshooting a git patch file end to end.

What a Git Patch File Actually Is

A patch file is plain text describing how to turn one version of a file into another — nothing more. It isn't a binary format, it isn't git-specific at the byte level, and you can open one in any text editor and read exactly what it does before running anything against it.

diff --git a/src/config.ts b/src/config.ts
index 3b4c5d6..f4a9c21 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -12,3 +12,5 @@ export const config = {
   timeout: 3000,
   retries: 3,
+  backoff: 500,
+  maxBackoff: 5000,
 };

Reading it top to bottom: diff --git a/... b/... names the file on each side (git always uses a/ and b/ prefixes here, regardless of your actual directory names); index records the before/after blob hashes and the file mode; --- and +++ repeat the file paths in the format the hunks below reference; and each @@ -12,3 +12,5 @@ line is a hunk header — the numbers are starting line and line count for the old and new versions of that region. Lines starting with a space are unchanged context, - is a removed line, + is an added one. This is the unified diff format at its core; the dedicated guide covers every header variant and edge case if you want the full spec rather than the working summary.

Anatomy of a Git Patch Hunk diff --git a/config.ts b/config.ts index 3b4c5d6..f4a9c21 100644 --- a/config.ts +++ b/config.ts @@ -12,3 +12,4 @@ timeout: 3000, - retries: 3, + retries: 5, + backoff: 500, maxRetries: 8, diff --git line names both sides, a/ and b/ index line before..after hash + mode --- / +++ lines old path / new path repeated Hunk header old & new start/count Line markers space = context, − = removed + = added Every field above the marker column is metadata; the marker column is what actually changes.
Every part of a patch hunk header identifies something specific — file names, blob hashes, or the line range a hunk targets.

What makes it a git patch file specifically, rather than a plain POSIX diff, is mostly the header — the diff --git line, the index line, and (when generated with git format-patch) an email-style header block above the diff carrying commit metadata. The underlying hunk syntax traces back to the classic Unix diff and patch tools; if you've never worked with those directly, the guide to the Unix diff command is useful background — git's patch format is a superset of the same idea, not a replacement for it.

git diff vs git format-patch: Two Ways to Make a Patch

Both commands produce a patch. Which one to reach for depends on a single question: does the person applying it need to know who wrote this and why, or just what changed? The table below breaks down exactly when a plain git diff patch is enough and when format-patch's extra metadata earns its keep, including how GitHub's own .patch URL suffix fits into the same picture.

Aspect git diff git format-patch GitHub .patch URL
Output Raw unified diff, content only, no metadata One mbox-format file per commit, with metadata Same mbox format as format-patch, per commit
Filename Whatever you choose Auto-numbered, e.g. 0001-subject.patch pr-number.patch or sha.patch
Author/date/message preserved? No Yes — author, date, subject, full message Yes, since it's format-patch under the hood
Applied with git apply git am git am
Creates a commit on apply? No — working tree (and index, with a flag) only Yes, replays as a real commit Yes, same as format-patch
Best for One-off local diffs, WIP snapshots, non-git targets Sharing commits with authorship intact Pulling a specific PR or commit without cloning

GitHub also serves a .diff suffix on the same URLs — a single combined diff with no commit metadata, the GitHub-hosted equivalent of plain git diff output, applied with git apply instead of git am. Both suffixes are covered in full in the GitHub section below.

How to Create a Patch File with git diff

Call it create patch file git, git create patch from diff, or make patch from git diff — however it gets phrased, this is the rawest form: no metadata, just the change itself, redirected to a file.

# Uncommitted changes in the working tree (vs the index)
git diff > my-changes.patch

# Staged changes only (vs the last commit)
git diff --cached > staged.patch

# Between two commits
git diff abc123 def456 > range.patch

# Between two branches
git diff main feature-branch > branch.patch

# A single file only
git diff -- src/config.ts > config.patch

Every one of these is a git create patch operation with the same shape: git diff with whatever comparison arguments you'd normally use, piped into a file instead of your terminal. If the change touches binary files — images, compiled assets, lockfile-adjacent binaries — add --binary so the patch embeds the binary content instead of silently skipping it:

git diff --binary > with-binaries.patch

Every flag that controls what git diff compares and how it formats the output — ignoring whitespace, word-level diffs, context line counts, path filters — applies identically when the output is headed to a file instead of stdout; the full flag reference covers those in depth. The one thing a plain git diff patch can never carry is commit identity, since there's no commit involved at all — that's exactly the gap git format-patch fills next.

Same Change, Two Different Envelopes GIT DIFF — CONTENT ONLY diff --git a/config.ts b/config.ts --- a/config.ts +++ b/config.ts @@ -12 +12,3 @@ timeout: 3000, + retries: 5, + backoff: 500, git diff > file.patch content only, no metadata GIT FORMAT-PATCH — METADATA + CONTENT From 8f2a1b3 Mon Sep 17 2001 Date: Wed, 20 Aug 2026 Subject: [PATCH] Bump retries --- a/config.ts +++ b/config.ts @@ -12,0 +12,2 @@ + retries: 5, + backoff: 500, git format-patch metadata plus content
git diff produces content only; git format-patch wraps the identical diff in author, date, and subject headers.

How to Generate a Patch with git format-patch

git format-patch is the tool when generating a patch needs to preserve who wrote a change and why, not just show what it did. It writes one file per commit, in mbox format — the same format email clients use for a single message — with From, Date, and Subject headers above the diff — a shape inherited from the Linux kernel's patches-over-email workflow, which is why git's official git-format-patch documentation still describes the output in terms of what you would send to a mailing list. git generate patch, git make patch, github generate patch — whichever term brought you here, format-patch is the command behind all three whenever commit metadata matters, not just the diff content.

# One file per commit, comparing your branch against main
git format-patch main

# Just the most recent commit
git format-patch -1 HEAD

# The last three commits
git format-patch -3

# Everything since a specific commit, up to HEAD
git format-patch abc123..HEAD

# All commits combined into a single file instead of one-per-commit
git format-patch --stdout main > series.patch

git format-patch main against a three-commit branch produces three separate files, named and numbered automatically:

0001-Add-retry-logic-to-api-client.patch
0002-Fix-timeout-default.patch
0003-Add-backoff-config.patch

The numbering preserves commit order, which matters because git am replays them in that order later. Each filename is derived from its commit's subject line, sanitized into something filesystem-safe — useful on its own for skimming what a series contains before opening any of the files. This one-file-per-commit shape is also why format-patch pairs naturally with a cleaned-up, linear branch: if your commits still need reordering or combining first, squashing them or rebasing the branch beforehand keeps the resulting patch series from mirroring a messy work-in-progress history.

Grabbing a Patch from GitHub: the .patch and .diff URL Suffixes

GitHub serves both formats directly from any pull request or commit URL — append .patch or .diff and the same page returns plain text instead of rendered HTML. No API token, no cloning, no extra tooling.

# format-patch style: per-commit, with author/date/message
https://github.com/owner/repo/pull/123.patch

# Single combined diff: content only, no metadata
https://github.com/owner/repo/pull/123.diff

# Same trick works on a single commit URL
https://github.com/owner/repo/commit/abc123def.patch

Grabbing a github patch or a github patch file this way — sometimes phrased as apply github patch, since the download and the apply usually happen back to back — needs nothing but curl and the right suffix:

# Download, then apply as a real commit with original authorship
curl -L https://github.com/owner/repo/pull/123.patch -o pr-123.patch
git am pr-123.patch

# Or pipe straight through, no intermediate file
curl -L https://github.com/owner/repo/pull/123.patch | git am

# .diff instead: single diff, no commit metadata, apply with git apply
curl -L https://github.com/owner/repo/pull/123.diff | git apply

Note which command pairs with which suffix: .patch is mbox format, so it goes to git am; .diff is a bare unified diff, so it goes to git apply. Feeding a .diff file to git am fails outright — there's no mbox header for it to parse — and that mismatch is one of the most common "why won't this patch apply" reports for anyone new to pulling patches from GitHub directly.

GitHub PR URL: .patch vs .diff .../pull/123 pull request URL .patch mbox format, per commit .diff single combined diff git am applies + commits, author preserved git apply working tree only, no commit ! Mismatched pairing: .diff piped into git am fails no mbox header to parse — always match the suffix to its command
.patch is mbox format for git am; .diff is a bare unified diff for git apply — cross the pairing and the apply fails outright.

Read the Patch Before You Apply It

Every guide above this line in most git patch tutorials stops at "apply it." A patch you wrote yourself, sure — go ahead. A patch that showed up in a bug report, a Slack message, or a PR from someone outside your org is a different situation: it's arbitrary file content about to be written into your working tree, and git apply will do exactly what it's told, no questions asked.

The command-line half of that discipline is two flags already covered above: git apply --check confirms it applies cleanly without touching a file, and git apply --stat shows the diffstat — which files, how many lines each. Neither one tells you whether the change is what it claims to be. For that, you need to actually read the diff, and a patch file full of @@ hunks and +/- markers is a rough read in a terminal once it's more than a few dozen lines.

Diff Checker — the free Chrome extension this site is built around, also usable directly at diffchecker.pro — doesn't know what a commit is and has no git integration; it's a Monaco-based editor that renders a live comparison between whatever text sits in its two panes, with a Split/Unified view toggle and three compare methods (Smart Diff, Ignore Whitespace, and Classic (LCS)). Set expectations correctly on one point: language highlighting is auto-detected from the content, and a .patch file isn't a language it recognises, so patch text lands as plain text rather than coloured syntax. That's a plain-text tool, not a patch parser — but it's exactly the right shape for two workflows a patch tutorial should cover and usually doesn't.

Workflow one: read the patch itself, before running anything. Put the .patch text in one pane and the current version of the file it targets in the other. Both panes are directly editable, so pasting into each one by hand works; the toolbar's Paste button is the shortcut, though note it fills the first empty pane rather than letting you choose, and falls back to overwriting the left one when both already hold text — so paste the patch first, then the file. Reading the two side by side is the point: you can see at a glance whether the context lines a hunk expects still exist in that file, or whether the file has drifted out from under the patch, which is exactly the situation covered next in when a patch won't apply.

Workflow two: verify what the patch actually did, after applying it. On a scratch branch — stash or commit anything already in progress first so there's nothing to lose — copy the target file's current contents into the left pane, run git apply for real, then copy the modified file into the right pane. This is where Show Diff Only earns its keep — collapsing every unchanged run down to a context window of 0, 1, 2, 3, or 5 lines turns the result into a short, readable list of exactly what changed, independent of whatever the patch's authors claimed it does in a commit message or PR description. If the result looks wrong, discarding the local changes resets the scratch branch cleanly for another attempt.

What to actually look for while reading an untrusted patch, specifically: files touched that have nothing to do with the patch's stated purpose, any change to CI configuration, build scripts, or lockfiles, anything in a postinstall or similar hook, and hunks in files far from what the description mentions. A patch that claims to "fix a typo in the README" and also edits package.json's scripts block is worth reading twice before it touches your machine — exactly the kind of thing that's obvious in a side-by-side view and easy to miss scanning +/- lines in a terminal.

Two Workflows for Trusting a Patch READ BEFORE APPLYING patch.diff --- a/config.ts +++ b/config.ts @@ -12 +12,3 @@ timeout: 3000, + retries: 5, + backoff: 500, config.ts (current) timeout: 3000, retries: 3, backoff: 200, pool: 10, maxRetries: 8, Compare patch text vs. the file it targets Paste Split / Unified Diff Only Do this before git apply ever touches a file VERIFY AFTER APPLYING before apply timeout: 3000, retries: 3, backoff: 200, pool: 10, after apply timeout: 3000, retries: 5, backoff: 500, pool: 10, Confirm exactly what the patch changed Paste Split / Unified Diff Only Do this on a scratch branch, after the real apply
Diff Checker isn't a patch parser — it's a plain-text comparison you point at a patch before applying it, and at the result after.

Worth being precise about what this workflow is not: Diff Checker has no unified-diff parser and no hunk-header awareness, so it renders patch text as plain text rather than understanding it as a patch — it won't apply anything for you. Its file picker doesn't list .patch or .diff among the extensions it offers either, so either switch the dialog to All Files, rename a local copy to .txt, or just paste the text, which is faster anyway. That's a deliberate, honest limitation, not a missing feature to route around — the two workflows above only ever need plain-text comparison, which is precisely what the tool does well.

How to Apply a Git Patch with git apply

How to apply a git patch with the most direct tool available: git apply reads a unified diff and writes the described changes straight into your working tree. Whether it's phrased as git apply diff, git apply diff patch, or git apply diff patch file, the command underneath is identical — point it at the file and it does the rest.

# Apply to the working tree only — no commit, no index change
git apply my-changes.patch

# Apply to the working tree *and* stage the result in the index
git apply --index my-changes.patch

# Apply into the index only, leave the working tree files untouched
git apply --cached my-changes.patch

The default behavior is worth internalizing precisely: plain git apply never creates a commit and never touches the index unless you tell it to with --index or --cached. That makes it an all-or-nothing, working-tree-level operation by default — exactly the right tool for the git apply diff use case where you just want the file contents changed and you'll decide separately whether and how to commit them.

git apply vs git am: Which One and When

git apply and git am both take a patch and change your working tree, but they answer different questions: "change these files" versus "replay this commit."

Aspect git apply git am
Expects Any unified diff — from git diff, another VCS, or hand-written An mbox-format file, one commit's email-style header plus diff
Creates a commit? Never, on its own Yes — one commit per file/message in the mbox stream
Preserves authorship? No — there's no commit to attach it to Yes — original author name, email, and date
Multi-file series Apply each file separately, or concatenate them first Feed a whole directory of NNNN-*.patch files in one call
Conflict recovery --reject writes .rej files; no continue/skip/abort --continue, --skip, --abort
Typical source git diff, a GitHub .diff URL git format-patch, a GitHub .patch URL, a mailing list

If you have direct access to the source repository and branch — rather than just a patch file someone handed you — moving a specific commit across branches is often better served by cherry-picking it directly, since that skips the export/import step entirely and still preserves authorship the same way git am does. Patches earn their keep specifically when you don't have that access, or when the target isn't a git repository the sender can push to at all.

Mid-series, git am also gives you a direct look at whatever commit is currently causing trouble: git am --show-current-patch=diff prints the diff of the patch that's paused the apply, without leaving the conflict state, which is often the fastest way to see exactly what a failing hunk was trying to do before deciding whether to fix it, skip it, or abort the whole series.

git apply vs git am: Two Different Endpoints patch file git apply Working tree changed No commit created mbox patch file git am Working tree changed AND new commit, author preserved loop Only git am can pause mid-series and resume --continue applies the fix, --skip drops the commit, --abort unwinds the whole series
git apply changes files and stops there; git am changes files, creates a commit, and — uniquely — can pause and resume mid-series.

Flags That Save You: --check, --stat, --3way, --whitespace, --reject

A handful of flags turn git apply from all-or-nothing into something more forgiving — or, in the case of the first two, into a way to inspect before committing to anything. The full list is in git's official git-apply documentation; these are the ones that actually come up.

# Dry run — confirms it would apply cleanly, touches nothing
git apply --check my-changes.patch

# Diffstat only — files and line counts, no content
git apply --stat my-changes.patch

# File mode changes and detected renames, without applying
git apply --summary my-changes.patch

--check exits non-zero and prints the specific hunks that would fail, which makes it the first thing worth running on any patch you didn't write yourself — cheap, safe, and it tells you immediately whether the rest of this section even applies.

# Fall back to a three-way merge using the blobs referenced
# in the patch's index line, instead of failing outright
git apply --3way my-changes.patch

--3way is the flag most worth knowing about and least often used. A plain git apply is strictly all-or-nothing: if the context around a hunk doesn't match, the whole patch fails. --3way instead looks up the blob hashes recorded in the patch's index line, and if your repository has those blobs (usually because the patch came from a commit in your own history), it performs a real three-way merge — which can succeed where a direct apply would fail, but can also leave <<<<<<< conflict markers in the working tree for you to resolve by hand, unlike plain apply, which never leaves partial results behind.

# Whitespace-only mismatches: fix, warn, error, or ignore
git apply --whitespace=fix my-changes.patch
git apply --whitespace=warn my-changes.patch
git apply --whitespace=error my-changes.patch
git apply --whitespace=nowarn my-changes.patch

# Apply what you can, write .rej files for the hunks that fail
git apply --reject my-changes.patch

--whitespace=fix corrects trailing whitespace and indentation-only mismatches instead of treating them as apply failures — useful when a patch was generated on a machine with different editor settings. It isn't quiet about it: each offending line is echoed, followed by warning: 1 line applied after fixing whitespace errors., so you can still see what it touched. --reject is the opposite philosophy from --3way: rather than trying harder to make everything apply, it applies whatever hunks succeed cleanly and writes the rest out as <filename>.rej files, so you can inspect and hand-apply just the parts that didn't go in automatically.

When a Patch Won't Apply: Conflicts and Fixes

$ git apply my-changes.patch
error: patch failed: src/config.ts:12
error: src/config.ts: patch does not apply

The root cause is almost always the same: git apply matches a hunk by its context lines and content, not by line number. If the target file has changed since the patch was generated — even a few lines added or removed elsewhere in the file — the context a hunk expects to find at "line 12" may no longer be there, and the whole hunk fails even though the actual change it's trying to make might still make perfect sense.

Why Context Drift Breaks a Patch PATCH EXPECTS — LINE 12 10 retries: 3, 11 backoff: 500, 12 timeout: 3000, 13 maxRetries: 8, 14 pool: 10, Hunk targets line 12 FILE NOW — DRIFTED 10 retries: 3, 11 backoff: 500, 12 logLevel: 'info', 13 retryJitter: true, 14 timeout: 3000, Same content now sits at line 14 git apply matches hunks by content, not line number — drift breaks the match
Two lines inserted above the hunk's target region push the expected content down, so the patch's context no longer lines up and the apply fails.

The fix ladder, roughly in order of how often each one resolves it:

  • Confirm the target file, not the patch, is the problem. git apply --check my-changes.patch first — if it fails the same way, the file really has drifted.
  • Try a three-way merge instead of a direct apply. git apply --3way my-changes.patch — if the referenced blobs exist locally, this often succeeds where a direct apply fails, leaving conflict markers to resolve by hand if it can't fully reconcile.
  • Check the path-stripping level. A patch generated from a different directory depth (a subdirectory, a differently named clone) has paths that don't line up with yours. -p<n> strips n leading path components before matching, and --directory=<dir> prepends a directory instead — try git apply -p2 my-changes.patch or similar if the default -p1 isn't matching your layout.
  • Rule out whitespace as the actual cause. git apply --whitespace=fix my-changes.patch — line-ending or trailing-space differences between the machine that generated the patch and yours are a common, easy-to-miss culprit.
  • Take what you can get. git apply --reject my-changes.patch applies every hunk that matches cleanly and writes .rej files for the rest, so you can manually merge just the parts that didn't go in.

For a patch applied through git am instead, the same underlying mismatch shows up as a paused series rather than a flat failure — git am --show-current-patch=diff shows what the stuck commit was trying to do, then git am --continue resumes after you've resolved it by hand and staged the result, git am --skip drops the current commit from the series entirely, and git am --abort unwinds the whole thing back to where you started. If nothing here resolves it and you'd rather start clean, discarding local changes and re-applying from scratch is often faster than untangling a half-applied patch by hand.

Reversing a Patch with git apply -R

A patch applied with plain git apply never became a commit, so there's nothing to revert in the commit-history sense — but the same patch file can undo its own change, using -R (or --reverse) to run every hunk backward.

# Undo a patch applied with git apply
git apply -R my-changes.patch

# Equivalent long form
git apply --reverse my-changes.patch

# Dry-run the reversal first, same as any other apply
git apply -R --check my-changes.patch

This only works cleanly if the working tree still looks like it did right after the patch went in — the same context-matching rules from the conflicts section apply in reverse. If the patch instead went in through git am and became a real commit, reversing at the file level isn't the right layer — git revert <commit> is, since it creates a new commit that undoes the change while keeping the original in history, rather than rewriting or dropping anything that's already shared.

Binary Files, Renames, and Other Edge Cases

A few situations don't fit the plain-text hunk model cleanly and need their own handling.

Binary files. A normal git diff carries no binary content at all. It says so rather than failing quietly — the whole diff for a changed image is one line reading Binary files a/logo.png and b/logo.png differ, with no hunks under it. Generating a patch that actually carries the change requires --binary at creation time, and applying one that contains binary hunks needs git apply --binary to write that content back out.

# Generate, including binary content
git diff --binary > with-binaries.patch

# Apply, writing binary hunks back to disk
git apply --binary with-binaries.patch

Renames. Git detects renames heuristically when generating a diff (a file that disappeared and a near-identical one that appeared nearby), and both git diff and git format-patch represent a detected rename as its own diff header rather than a delete-plus-add pair. git apply --summary lists exactly which files a patch renames or changes the mode of, without applying anything — worth running on an unfamiliar patch alongside --stat, since a rename can be easy to miss scanning hunks alone.

Path mismatches. -p<n> strips n leading path components from each file path in the patch before matching against your working tree — -p1 (stripping the a/ / b/ prefix) is the default and what both git diff and format-patch produce, so you rarely need to touch it for patches generated by git itself. It matters more for patches from other tools, or ones generated a directory level off from where you're applying them. --directory=<dir> does the opposite — it prepends a directory to every path instead of stripping one, useful when applying a patch generated for a subdirectory against the repository root.

Quick Reference: Every Patch Command in One Table

Every command from every section above, in one place — from the plain git diff redirect through git apply diff patch file handling and the full git am conflict loop.

Command What It Does
git diff > file.patchCreate a raw patch from uncommitted changes
git diff --cached > file.patchCreate a patch from staged changes only
git diff --binary > file.patchCreate a patch that includes binary file content
git format-patch mainGenerate one metadata-rich patch file per commit since main
git format-patch -1 HEADGenerate a patch for just the most recent commit
git format-patch --stdout > series.patchCombine a whole series into one file
git apply file.patchApply a patch to the working tree only
git apply --index file.patchApply and stage the result in the index
git apply --cached file.patchApply into the index only, skip the working tree
git apply --check file.patchDry run — confirm it applies, touch nothing
git apply --stat file.patchShow the diffstat without applying
git apply --summary file.patchShow mode changes and renames without applying
git apply --3way file.patchFall back to a three-way merge instead of failing outright
git apply --reject file.patchApply what matches, write .rej files for the rest
git apply --whitespace=fix file.patchAuto-correct whitespace-only mismatches
git apply -R file.patchReverse an already-applied patch
git apply -p2 file.patchStrip two leading path components before matching
git apply --binary file.patchApply a patch containing binary hunks
git am file.patchApply an mbox patch as a real commit, authorship preserved
git am --continueResume an am series after resolving a conflict
git am --skipDrop the current commit from an am series
git am --abortUnwind the whole am series back to the start
git am --show-current-patch=diffShow the diff of the commit currently paused
curl -L url.patch | git amDownload and apply a GitHub PR/commit patch in one step

Frequently Asked Questions

How do I apply a patch file in git?

Run git apply <patchfile> for a working-tree-only apply — no commit gets created, and the index isn't touched unless you add --index or --cached. If the file came from git format-patch or a GitHub .patch URL, use git am <patchfile> instead — it replays the patch as a real commit with the original author, date, and message intact. When you're not sure a patch will apply cleanly, run git apply --check first.

What's the difference between git format-patch and git diff?

git diff > file.patch produces a raw unified diff with no metadata — content only — applied with git apply, and it never becomes a commit by itself. git format-patch produces one file per commit in mbox format, complete with author, date, subject line, and commit message, applied with git am, which replays each file as a genuine commit with the original authorship preserved.

How do I check if a patch applies without applying it?

git apply --check <patchfile> runs a dry run — it exits non-zero and prints exactly which hunks would fail, without touching a single file in your working tree. Pair it with git apply --stat to see the diffstat and git apply --summary to see file mode changes and detected renames before you commit to the real apply.

How do I reverse a git patch?

git apply -R <patchfile> (or the long form --reverse) undoes a patch that was applied with git apply, as long as your working tree still matches the post-apply state closely enough for the reversed hunks to find their context. If the patch was applied with git am and became a real commit, git revert <commit> is the right tool instead, since it reverses at the commit level rather than the file level.

What's the difference between git apply and git am?

git apply takes any unified diff and applies it to the working tree — and the index, with --index — without ever creating a commit. git am is built specifically for format-patch-style mbox files: it applies the diff and creates a commit, preserving the original author and message, and it gives you --continue, --skip, and --abort for handling conflicts mid-series, none of which exist for plain git apply.