Home / Alt manpages / patch(1)

  • patch(1)
  • User command
  • linux

Apply a Unified Diff Safely with patch

Get the strip level wrong and patch will happily edit a file that just happens to share a name, so check the paths before you trust the result. You'll preview and apply a unified diff to a working tree, understand the -p1 path choice, and handle rejects without guessing. The examples use GNU patch 2.7.6, supplied by the installed patch package.

Allow about fifteen minutes. You need a shell, a patch file and a copy of the source tree at the version the patch expects. Applying a patch changes files in place, so make a disposable copy or commit current work before you start. Elevated privileges aren't normally needed for files you own.

1. Check the command and preserve a recovery point

Confirm which executable will run and record the current state of the tree:

$ command -v patch
/usr/bin/patch
$ patch --version
GNU patch 2.7.6
$ git status --short

That last command is only useful in a Git working tree. If it reports changes, commit them or copy the tree before applying the patch. For a non-Git directory, make a separate copy with an explicit destination:

$ cp -a /path/to/project /path/to/project.before-patch

Don't reach for sudo just because a patch touches source files. Use it only when the target directory is deliberately owned by another account, and check the resulting ownership afterwards.

Checkpoint

You've identified the input tree, the patch file, and a way to restore the original files.

2. Read the patch paths before choosing -p

A typical Git-style patch names the same file as a/src/example.txt and b/src/example.txt. The -p option strips leading pathname components from names read from the patch: with -p1, the leading a/ or b/ disappears, so the command looks for src/example.txt below your current directory.

$ sed -n '1,12p' /path/to/change.patch
diff --git a/src/example.txt b/src/example.txt
--- a/src/example.txt
+++ b/src/example.txt
@@ -1,3 +1,3 @@
 alpha
-old line
+new line
 omega
  • Run the command from the directory that should contain src/.
  • If headers say project/src/example.txt and you're already inside project/, strip that one extra level with -p1.
  • If the header already names a path relative to your current directory, use -p0.
  • Don't pick a strip level by trial and error against a live tree. A plausible path can still be the wrong file.
  • The short option needs its number: write -p1 or -p 1, never a bare -p.

3. Preview the change with --dry-run

Use the same directory and options you intend for the real operation, but add --dry-run:

$ cd /path/to/project
$ patch --dry-run -p1 < /path/to/change.patch
checking file src/example.txt

A dry run reports what would happen without changing a thing. A clean preview doesn't prove the patch is semantically right, but it confirms the patch can find its target with this path interpretation. Inspect the patch and the named files if the command asks a question or reports a failed hunk.

Checkpoint

The dry run names only the files you expect and reports no failed hunks. If it selects an unexpected path, stop and fix the working directory or the -p value.

4. Apply the patch and verify the result

Once the preview is correct, drop --dry-run and apply the same input:

$ patch -p1 < /path/to/change.patch
patching file src/example.txt
$ git diff --check
$ git diff -- src/example.txt

A successful run returns status 0 once every hunk applies. git diff --check catches common whitespace errors, and the final diff lets you confirm the right lines changed. On a non-Git tree, inspect the edited file directly and compare it with the expected version.

By default patch writes the new content in place. Add -b for an explicit original alongside the edited file; the default simple backup suffix is normally .orig when no numbered backup is chosen:

$ patch -b -p1 < /path/to/change.patch
patching file src/example.txt
$ ls -l src/example.txt src/example.txt.orig

Recovery

A backup is a safety net, not a substitute for a tested recovery point. If the result is wrong, restore from version control or your copy. To reverse a backup made by the example:

$ cp --preserve=all src/example.txt.orig src/example.txt

Check the restored file before removing the backup. Don't run rm as part of an unreviewed recovery sequence.

5. Treat offsets and fuzz as warnings

patch can find a hunk at a different line from the number in its header. It may report an offset, or say it used fuzz by ignoring some context lines, meaning the file isn't exactly the version the patch was made against. A small offset can be harmless after nearby edits, but a large offset or fuzz can drop a change in the wrong place.

Warning

Review every warning and the resulting diff. For exact matching, apply to a clean checkout of the expected revision or stop when the preview reports a mismatch. Increasing the fuzz factor with -F makes matching more permissive and raises the chance of a faulty result, it's not a general repair switch.

6. Resolve a failed or reversed patch

If a hunk can't be installed, patch normally writes the rejected hunk to a file ending in .rej and returns status 1. Status 2 means more serious trouble. Capture the status when scripting:

patch -p1 < /path/to/change.patch
status=$?
if [ "$status" -ne 0 ]; then
    printf 'patch failed with status %s\n' "$status" >&2
    exit "$status"
fi

Warning

Don't continue a batch of dependent patches after status 1. Inspect the edited file and the .rej file, compare the target against the patch's expected base, and restore your recovery copy if the partial result isn't wanted. A reject is a review task, not permission to paste the rejected text somewhere arbitrary.

When the first hunk doesn't match, GNU patch may test whether the patch looks already applied and ask whether to reverse it:

Reversed (or previously applied) patch detected!  Skipping patch.

Answering yes to reverse a patch changes the files in the opposite direction. Use -R only once you've verified the old and new sides really are swapped and you actually want to undo the change. Use -N when an automated process must skip the reverse-application check rather than asking. Neither option repairs a patch made for the wrong source version.

7. Keep automation explicit

For scripts, supply the input with -i or standard input, set the directory with -d, and check the exit status. The patch file usually supplies target names, but an ambiguous or incomplete header can make patch ask which file to edit, review such a patch rather than forcing it blindly with -f.

$ patch --dry-run --forward --directory=/path/to/project --strip=1 \
    --input=/path/to/change.patch
checking file src/example.txt

--forward prevents the normal reverse-patch check. Keep it inside a separately reviewed, repeatable deployment step, and still treat a non-zero status as failure. The command changes files as soon as the dry run is replaced by a real run, so leave service restarts, rebuilds and deployments until after the patched tree has been reviewed and tested.

Done means

  • Identified the patch source and target version, with a recovery copy or commit available.
  • Checked the header paths and tested the chosen -p value with --dry-run.
  • Confirmed status 0 on the real run and reviewed the resulting diff or file contents.
  • Investigated every offset, fuzz, reject and reverse-patch message rather than ignoring it.
  • Kept service and deployment actions separate, and forced nothing into an unverified tree.