SysTutorials

Git Patches: Create, Apply, and Debug Issues

· updated April 11, 2026

The standard way to generate patches from git commits is git format-patch. This creates email-ready patch files that include commit messages, author information, and metadata.

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

# Create patches for the last N commits
git format-patch -3

# Create patches from a specific commit onwards
git format-patch abc1234..HEAD

# Create patches from a range of commits
git format-patch abc1234..def5678

# Output patches to a directory
git format-patch -o /tmp/patches -1

The -1 flag tells git how many commits back to start from. Each commit generates a separate numbered patch file like 0001-commit-message.patch.

For a single logical change across multiple commits, use --stdout to combine them:

git format-patch -3 --stdout > my-feature.patch

Customizing patch output

Control what gets included in your patches:

# Include a cover letter (useful for series)
git format-patch -3 --cover-letter

# Use a custom prefix instead of "PATCH"
git format-patch -3 --subject-prefix="RFC"

# Number patches even if there's only one
git format-patch -1 -N

# Include diffstat
git format-patch -1 --stat

# Sign patches with GPG
git format-patch -1 -S

# Create patches with a custom subject line format
git format-patch -1 --pretty=format:"%h %s"

Applying patches

Use git apply for simple patches or git am (apply mail) for patches created with git format-patch. The key difference: git am preserves commits and metadata, while git apply just applies the diff without creating new commits.

With git am (preferred for format-patch)

git am handles email headers, author info, and commit metadata properly:

# Apply a single patch
git am 0001-fix-bug.patch

# Apply all patches in a directory
git am /tmp/patches/*.patch

# Continue after resolving conflicts
git am --continue

# Skip a problematic patch
git am --skip

# Abort the entire operation
git am --abort

# Apply without verifying GPG signatures
git am --no-verify

# Apply and sign commits with your GPG key
git am -S

With git apply

git apply just applies the diff without creating commits. Useful for non-git projects, testing changes before committing, or applying partial diffs:

# Apply a patch
git apply my-patch.patch

# Check if a patch applies cleanly (dry run)
git apply --check my-patch.patch

# Apply with whitespace fixes (tabs/spaces)
git apply --whitespace=fix my-patch.patch

# Reverse a patch
git apply -R my-patch.patch

# Apply with strict whitespace checking
git apply --whitespace=error my-patch.patch

Handling patch conflicts

When patches don’t apply cleanly due to conflicting changes, resolve them manually:

# After resolving conflicts in your editor
git add .
git am --continue

# Or to edit the commit message during apply
git am --allow-empty

# Abort if things get messy
git am --abort

For complex scenarios, use git apply --reject to generate .rej files for manual inspection:

git apply --reject my-patch.patch

# Review the .rej files
cat file.rej

# Manually fix the changes, then add and commit
git add .
git commit

If you’re applying a series of patches and one fails, you have options:

# Skip just that one patch and continue with the rest
git am --skip

# Reset and try a different approach (e.g., cherry-pick instead)
git am --abort
git cherry-pick abc1234..def5678

Patch workflow example

A typical workflow for receiving and testing patches:

# Create a feature branch for testing
git checkout -b test-patch

# Apply patches with am (preserves commits)
git am /path/to/patches/*.patch

# Review changes
git log --oneline -5
git diff main..HEAD

# If everything looks good, merge to main
git checkout main
git merge test-patch

# If there are issues, abort and try again
git am --abort
git checkout test-patch

Creating patches from uncommitted changes

To create a patch from your working directory without committing:

# Patch of all unstaged changes
git diff > local-changes.patch

# Patch of staged changes only
git diff --cached > staged.patch

# Patch including both staged and unstaged
git diff HEAD > all-changes.patch

# Apply uncommitted patches with git apply
git apply local-changes.patch

This approach works well for sharing work-in-progress changes or applying changes across branches without creating intermediate commits.

Combining patches and stashing

For temporary work, stashes can be cleaner than patches:

# Save uncommitted changes to a stash
git stash

# Later, apply the stash
git stash pop

# Export a stash as a patch
git stash show -p stash@{0} > my-stash.patch

Verifying patches before applying

Before applying patches from untrusted sources:

# Preview a patch without applying it
git apply --check my-patch.patch

# Review the actual diff content
git diff < my-patch.patch

# Check patch statistics
git apply --stat my-patch.patch

If git apply --check reports errors, the patch won’t apply cleanly and you’ll need to manually adjust it or resolve conflicts during git am.

← All posts