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:
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:
| Toolchain | Create the patch | Apply the patch | Best for |
|---|---|---|---|
| diff / patch (POSIX) | diff -u old.js new.js > changes.patch | patch < changes.patch (or patch -p1 < for a/ b/ prefixes) | Any files, no Git needed; tarballs, config files, cross-project fixes |
| git diff / git apply | git diff > changes.patch | git apply changes.patch | Moving uncommitted changes between clones or branches without a commit |
| git format-patch / git am | git format-patch -1 (or main..feature) | git am 0001-*.patch | Contributing 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
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.
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.