Home / Alt manpages / patch(1)

  • patch(1)
  • User command
  • linux

Apply a Unified Diff Safely with patch

You will 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 the current work before you start. Elevated privileges are not 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 final command is only useful in a Git working tree. If it reports changes, either commit them or copy the tree before applying the patch. For a non-Git directory, make a separate copy with a destination chosen explicitly:

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

Do not use sudo just because a patch changes source files. Use it only when the target directory is deliberately owned by another account, and review the resulting ownership before continuing.

Checkpoint

You have 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 the headers instead say project/src/example.txt and you are already in project, use -p1 to remove project/. If the header already names a path relative to your current directory, use -p0. Do not choose a strip level by trial and error against a live tree: a plausible path can still be the wrong file.

The short option requires its number. Write -p1 or -p 1, not a bare -p.

3. Preview the change with --dry-run

Use the same directory and options you intend to use 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 the files. A clean preview does not prove that the patch is semantically right, but it confirms that the patch can find its target with this path interpretation. Inspect the patch itself 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 -p value.

4. Apply the patch and verify the result

Once the preview is correct, remove --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 when all hunks apply. git diff --check catches common whitespace errors, while the final diff lets you confirm the intended lines changed. For a non-Git tree, inspect the edited file and compare it with the expected new version.

By default, patch writes the new contents in place. If you want an explicit original alongside the edited file, add -b; the default simple backup suffix is normally .orig when no numbered backup is selected:

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

Backups are a safety net, not a substitute for a tested recovery point. If the result is wrong, restore from version control or your copy. For a backup made by the example, the reversible operation is:

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

Check the restored file before removing the backup. Do not 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 the header. It may report an offset, or say that it used fuzz by ignoring some context lines. That means the file is not exactly the version used to create the patch. A small offset can be harmless after nearby edits, but a large offset or fuzz can place a change in the wrong location.

Review every warning and the resulting diff. If exact matching is required, use a stricter workflow: 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 increases the chance of a faulty result, so it is not a general repair switch.

6. Resolve a failed or reversed patch

If a hunk cannot be installed, patch normally writes the rejected hunk to a file ending in .rej and returns status 1. Status 2 indicates 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

Do not continue a batch of dependent patches after status 1. Inspect the edited file and the .rej file, compare the target with the patch's expected base, and restore the recovery copy if the partial result is not wanted. A reject is a review task, not permission to paste the rejected text into an arbitrary location.

When the first hunk does not match, GNU patch may test whether the patch appears to have been applied already and ask whether to reverse it. An already-applied patch often produces a message like this:

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

Answering yes to reverse a patch changes the files in the opposite direction. Use -R only when you have verified that the old and new sides really are swapped and you intentionally want to undo the change. Use -N when an automated process must skip reverse-application checks rather than asking questions. 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 instead of 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 with a separately reviewed, repeatable deployment step, and still treat a non-zero status as a 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

  • The patch source and target version were identified, with a recovery copy or commit available.
  • The header paths were checked and the chosen -p value was tested with --dry-run.
  • The real run returned status 0, and the resulting diff or file contents were reviewed.
  • Offsets, fuzz, rejects and reverse-patch messages were treated as warnings requiring investigation.
  • No patch was forced into an unverified tree, and any service or deployment action was kept separate.