Development

How do I create and apply patch files from diffs?

Patch files are a standard way to share and apply changes. Learn how to create patch files from diffs and apply them to other codebases.

By Inventive HQ Team

To create a patch file, capture the differences between two versions of code as a unified diff and save it to a file; to apply one, feed that file to patch or git apply on the target code. The two common recipes are: diff -u old.js new.js > changes.patch then patch < changes.patch for arbitrary files, or git diff > changes.patch then git apply changes.patch inside a Git repository. For sharing commits with their message and author intact, use git format-patch to create and git am to apply. A patch is just a portable, version-control-agnostic text file describing what to add and remove, line by line.

That's the summary an AI overview will give you. The part it can't give you is knowing which of the three toolchains to reach for, why a patch that looks correct still refuses to apply, and how the -p strip level actually decides where the changes land — which is where most patch frustration actually comes from. The rest of this article walks through each path with commands you can copy, and a decision table for picking the right one.

Understanding Patch Files

A patch file is a text file containing the differences between two versions of code, generated in a standard format that any developer can apply to their own version of the code. Patch files are one of the oldest and most reliable ways to share code changes across teams, projects, and communities.

Whether you're contributing to open-source projects, sharing fixes with team members, or maintaining compatibility across versions, patch files provide a portable, version-control-independent way to apply changes.

The whole lifecycle is just three stages — produce a diff, save it as a .patch file, and replay it somewhere else:

The patch lifecycle: diff to .patch file to apply Three stages connected by arrows: generating a diff between two versions, saving it as a patch file, and applying that patch to target code. A pulse travels left to right along the path. From difference to applied change 1. Diff compare old vs new diff -u / git diff 2. changes.patch portable text file > changes.patch 3. Apply replay on target patch / git apply

Which toolchain should I use?

There are three ways to make and apply a patch, and they are not interchangeable. Plain diff/patch works on any files, anywhere, with no version control. git diff/git apply moves raw changes between working trees. git format-patch/git am moves whole commits — message, author, and date included. Pick by what you're moving and where it's going:

ToolchainCreate the patchApply the patchBest for
diff / patch (POSIX)diff -u old.js new.js > changes.patchpatch < changes.patch (or patch -p1 < for a/ b/ prefixes)Any files, no Git needed; tarballs, config files, cross-project fixes
git diff / git applygit diff > changes.patchgit apply changes.patchMoving uncommitted changes between clones or branches without a commit
git format-patch / git amgit format-patch -1 (or main..feature)git am 0001-*.patchContributing commits by email; preserving message, author, and date

The quick rule: no Git → diff/patch; Git but you only want the changes → git diff/git apply; Git and you want the commit history → git format-patch/git am.

Creating Patch Files from Diffs

Basic Patch Creation with Git

The simplest way to create patch files is using Git:

# Create a patch from the latest commit
git format-patch -1

# This creates: 0001-your-commit-message.patch

# Create patches for multiple commits
git format-patch -5
# Creates: 0001-.patch, 0002-.patch, etc.

# Create patch from two commits
git format-patch -2 HEAD

Diff-Based Patch Creation

For non-Git projects or comparing arbitrary files:

# Create unified diff patch
diff -u original.js modified.js > changes.patch

# Comparing directories
diff -ruN original-dir/ modified-dir/ > changes.patch

Git Diff to Patch

# Create patch from uncommitted changes
git diff > uncommitted-changes.patch

# Create patch comparing branches
git diff main feature-branch > feature.patch

# Create patch comparing commits
git diff abc123 def456 > changes.patch

# Create patch for specific file
git diff main -- path/to/file.js > file-changes.patch

Patch File Format

Understanding Patch File Structure

diff --git a/file.js b/file.js
index abc1234..def5678 100644
--- a/file.js
+++ b/file.js
@@ -1,7 +1,8 @@
 function calculateTotal(items) {
-  let total = 0;
-  for (let i = 0; i < items.length; i++) {
-    total += items[i].price;
+  return items.reduce((total, item) => {
+    return total + item.price;
   }
-  return total;
+  }, 0);
 }

Components:

  • Header: File paths (a/ = original, b/ = modified)
  • Line numbers: @@ -1,7 +1,8 @@ (7 lines starting at line 1 in original, 8 lines in modified)
  • Context: Lines with space prefix (unchanged)
  • Additions: Lines with + prefix
  • Removals: Lines with - prefix
Advertisement

Multi-File Patches

Patches can contain changes to multiple files:

diff --git a/file1.js b/file1.js
[changes to file1.js]

diff --git a/file2.js b/file2.js
[changes to file2.js]

diff --git a/file3.js b/file3.js
[changes to file3.js]

Apply all changes at once with one command.

Applying Patch Files

Need to eyeball the differences between two versions before you package them into a patch? Paste both into the diff checker below to see a clean unified diff first.

Loading interactive tool...

Using git apply

# Apply patch file
git apply changes.patch

# Check if patch applies cleanly
git apply --check changes.patch

# Apply with specific path
git apply --include="src/*" changes.patch

# Reject patch on failures
git apply --reject changes.patch

Using patch Command

# Standard patch command
patch < changes.patch

# Patch specific directory
cd project/
patch < ../changes.patch

# Show what would be patched without applying
patch --dry-run < changes.patch

# Apply with specific strip level
patch -p1 < changes.patch  # For git-generated patches
patch -p0 < changes.patch  # For diff-generated patches

Strip Levels Explained

The -p flag specifies how many directory levels to strip from file paths:

Patch file contains:

--- a/src/component.js
+++ b/src/component.js

Different strip levels:

patch -p0 < changes.patch
# Looks for: a/src/component.js

patch -p1 < changes.patch
# Looks for: src/component.js (strips "a/")

patch -p2 < changes.patch
# Looks for: component.js (strips "a/src/")

Git patches usually need -p1.

Creating Shareable Patches

Creating a Clean Patch for Email

# Format patch nicely for email
git format-patch -1 --stdout > my-change.patch

# For multiple commits
git format-patch -2 --stdout | cat > my-changes.patch

Creating Patch with Context

# Include more context lines (default 3)
git diff -U5 > generous-context.patch

# This helps patches apply in similar but not identical codebases

Creating Patch with Commit Message

# Git format-patch includes commit message
git format-patch -1

# Results in file that includes commit message that can be preserved
# when applying with: git am 0001-message.patch

Real-World Patch Workflows

Scenario 1: Contributing to Open Source

# Clone repository
git clone https://github.com/project/repo
cd repo

# Create feature branch
git checkout -b fix-bug

# Make changes
# ...commit changes...

# Create patch for submission
git format-patch origin/main

# Or create patch from feature branch
git diff main fix-bug > fix-bug.patch

# Send patch to project maintainers

Maintainers apply with:

patch < fix-bug.patch
# or
git apply fix-bug.patch

Scenario 2: Emergency Patch Deployment

# In production environment, identified bug needs emergency fix
# Rather than full deployment, deploy a patch

# Create patch from fixed version
git diff production staging > emergency-fix.patch

# Apply to production at customer sites
cd /production/code
patch -p1 < emergency-fix.patch

# Verify changes
git status

Scenario 3: Backporting Fixes

# Fix developed in main branch
git log --oneline main | head

# Need same fix in older release branch
git checkout release-1.0

# Apply main branch fix
git format-patch release-1.0...main -- src/buggy-file.js \
  | git am

# Or manually create and apply patch
git show main:file.js > fixed-file.js
git show release-1.0:file.js > old-file.js
diff -u old-file.js fixed-file.js > backport.patch
patch < backport.patch

Handling Patch Conflicts

When Patches Don't Apply Cleanly

# Try applying with conflict markers
patch -l < changes.patch  # --ignore-whitespace

# If still fails, patch creates .rej files
# file.js.rej contains rejected hunks

# Manually review rejected changes
cat file.js.rej

# Make manual adjustments
# Then apply remaining changes
patch -R < changes.patch  # Reverse if needed

Fuzzy Matching

# Use fuzzy patch application
patch -F3 < changes.patch

# -F3 allows up to 3 lines of fuzz when matching context

Advanced Patch Operations

Creating Patches from Specific Commits

# Patch for specific commit (not pushed)
git format-patch -1 abc1234

# Patches for commits in range
git format-patch main..feature-branch

# Patches for all unpushed commits
git format-patch origin/main..HEAD

Applying Patches with Git AM

# Apply patch AND preserve commit message
git am my-change.patch

# Apply multiple patches in order
git am *.patch

# Skip problematic patch
git am --skip

# Abort if problems occur
git am --abort

# Resolve conflicts then continue
git am --continue

Creating Binary Patches

# Binary files in patches
git diff --binary > binary-changes.patch

# Apply binary patch
git apply binary-changes.patch

Best Practices with Patches

1. Always Check Before Applying

# Verify patch applies cleanly
patch --dry-run < changes.patch
# or
git apply --check changes.patch

2. Include Context Information

# Document why patch exists
# Add commentary in email or README

3. Use Meaningful Patch Names

# Good
fix-authentication-token-refresh.patch
feature-dark-mode-support.patch
security-patch-sql-injection.patch

# Bad
fix.patch
changes.patch
update.patch

4. Sign Patches for Security

# Sign patch file
gpg --sign changes.patch

# Verify signature
gpg --verify changes.patch

5. Test Patches Thoroughly

# Test on clean checkout
git clone repo test-repo
cd test-repo
patch < ../changes.patch
# Run tests
npm test

Patch Management Tools

Quilt - Patch Stack Management

# Manage stacks of patches
quilt new fix.patch
quilt edit file.js
quilt refresh

# View patch stack
quilt series
quilt status

StGit - Stack of Git Patches

# Git-based patch management
stg new my-patch
stg push
stg pop
stg status

Troubleshooting Patches

Patch Doesn't Apply

Possible causes:

  • Different code versions
  • Whitespace differences
  • File paths don't match
  • Already applied

Solutions:

# Try different strip level
patch -p0 < changes.patch
patch -p1 < changes.patch

# Ignore whitespace
patch --ignore-whitespace < changes.patch

# See what would happen
patch --dry-run < changes.patch

# Check if already applied
grep -F "$(head -1 changes.patch)" target-file

Partial Application

# If some hunks fail, .rej files show what failed
cat file.js.rej

# Manually apply failed sections
# Then patch rest of file
patch < changes.patch

Conclusion

Patch files are a fundamental tool for sharing code changes, contributing to open source, and applying fixes across versions. By understanding how to create patches from diffs and apply them effectively, you can:

  • Contribute fixes to projects you don't directly control
  • Share code changes with team members
  • Deploy emergency fixes to production systems
  • Backport fixes to older release versions
  • Maintain compatibility across versions

Whether using simple diff and patch commands or Git's more sophisticated format-patch and git am tools, patch files remain one of the most reliable and portable ways to share and apply code changes across different environments, versions, and workflows.

Mastering patch creation and application is essential for any developer working in open source communities, maintaining multiple versions, or collaborating across distributed teams.

Frequently Asked Questions

How do I create a patch file from two files?

Use the diff command with the -u flag to produce a unified diff and redirect it to a file: diff -u original.js modified.js > changes.patch. The -u (unified) format is what almost every patch tool expects because it includes a few lines of surrounding context, which lets the patch apply even if the target file has shifted slightly. To diff whole directories, add -r (recursive) and -N (treat absent files as empty) so new files are included: diff -ruN original-dir/ modified-dir/ > changes.patch.

How do I apply a .patch file?

For a patch made with plain diff, run patch < changes.patch from the directory the paths are relative to. For a patch made with git diff or git format-patch, use git apply changes.patch (applies the changes to your working tree without committing) or git am changes.patch (applies the changes and recreates the commit with its original message and author). Always dry-run first: patch --dry-run < changes.patch or git apply --check changes.patch.

What is the difference between git apply and git am?

git apply takes a diff and modifies your working-tree files, leaving you to stage and commit the result yourself — it is a Git-aware version of the classic patch command. git am expects a patch created by git format-patch (which embeds the commit message, author, and date) and replays it as a real commit, preserving all that metadata. Use git apply for a bare set of changes; use git am when you want the original commit history recreated.

What does the -p1 option in patch mean?

The -p flag tells patch how many leading directory components to strip from the file paths inside the patch. Git patches label files as a/src/file.js and b/src/file.js, so patch -p1 strips the a/ prefix and looks for src/file.js — which is why git-generated patches almost always need -p1. A patch made with plain diff usually has no prefix, so it applies with -p0 (strip nothing). git apply understands the a//b/ convention automatically and needs no -p flag.

Why won't my patch apply cleanly?

The four usual causes are: the target file is a different version than the patch was made against; whitespace or line-ending differences (try patch --ignore-whitespace or git apply --ignore-whitespace); the strip level is wrong (try -p0 instead of -p1 or vice versa); or the patch was already applied. When patch fails partway it writes the failed hunks to a .rej file next to the target so you can apply them by hand. You can also loosen context matching with fuzz: patch -F3 allows up to three lines of mismatch.

How do I create a patch from a Git commit?

Use git format-patch, which turns commits into mailbox-formatted .patch files complete with the commit message and author. git format-patch -1 makes a patch for the most recent commit; git format-patch main..feature makes one file per commit on the feature branch that is not on main. Add --stdout to combine them into a single stream you can pipe or redirect. The recipient applies them in order with git am *.patch.

How do I reverse or undo an applied patch?

Re-run the same patch with the reverse flag. With the patch command that is patch -R < changes.patch; with Git it is git apply -R changes.patch (or git apply --reverse). This subtracts the changes the patch added, restoring the files to their pre-patch state, as long as the patch still matches. It is the standard way to back out a change you applied from a shared patch file.

Can a single patch file change multiple files?

Yes. A unified diff or a git diff simply concatenates the per-file diffs, each starting with its own header (--- / +++ for plain diff, or diff --git a/... b/... for Git). Applying the patch with a single patch, git apply, or git am command updates every file in it at once. This is why diff -ruN on two directory trees, or git diff across a branch, is enough to package an entire multi-file change into one shareable file.

patch filesdiffsversion controlcode changessoftware development