patch
Apply differences between files (patching)
TLDR
Apply a patch using a diff file (filenames must be included in the diff file)
Apply a patch to a specific file
Patch a file writing the result to a different file
Apply a patch to the current directory
Apply the reverse of a patch
SYNOPSIS
patch [options] [originalfile [patchfile]]
Common usage:
patch [options] < patchfile
PARAMETERS
-p NUM, --strip=NUM
Strip NUM leading slash-separated components from pathnames in the patch file. This is crucial when the patch file contains paths relative to a different root than where you're applying the patch.
-i FILE, --input=FILE
Read the patch from FILE instead of standard input.
-o FILE, --output=FILE
Write the output to FILE instead of modifying the original file in place.
-R, --reverse
Apply the patch in reverse, effectively undoing changes.
-E, --remove-empty-files
Remove any output files that become empty after patching.
-N, --forward
Ignore patches that appear to be already applied.
-F NUM, --fuzz=NUM
Set the maximum number of lines that can be ignored at the start and end of a hunk when looking for a place to install a patch. Defaults to 2.
-t, --batch
Do not ask any questions; skip files that do not match and exit if the patch file is not well-formed.
-d DIR, --directory=DIR
Change the current directory to DIR before looking for files.
-l, --ignore-whitespace
Ignore white space differences when comparing.
-v, --version
Print the version number of patch.
DESCRIPTION
The patch command applies changes to text files, typically source code. It reads instructions from a diff file (also known as a "patch file"), which contains a list of differences between an original file and a modified file. Patch then modifies the original file(s) according to these instructions. It's a fundamental utility in Unix-like systems, widely used in software development for distributing bug fixes, new features, or updates without needing to distribute entire new versions of files. Common diff formats supported include unified, context, and normal diffs. When patch cannot apply a change cleanly (e.g., if the original file has been modified in the same area), it will create "reject" files (with a .rej extension) indicating the failed portions. Its ability to strip leading directory components from filenames within the patch file makes it highly flexible for applying patches generated from different directory structures.
CAVEATS
Merge Conflicts: Patch is a line-oriented tool and does not perform sophisticated three-way merges. If the context surrounding a change in the original file has been modified, patch might fail to apply the hunk and create a .rej (reject) file, which requires manual resolution.
File Naming: The patch file must correctly identify the original file. If the file paths in the patch do not match the local file system (even after stripping leading components), patch will fail.
No Rollback: Unless you keep a backup of the original file, there's no automatic rollback mechanism if a patch causes issues. Using version control is highly recommended.
Whitespace Sensitivity: While `-l` can help, patch can be sensitive to differing whitespace styles (tabs vs. spaces, line endings) between the patch and the target file.
TYPICAL WORKFLOW
The common workflow involves first creating a patch file using `diff` (e.g., `diff -u original_file modified_file > my_changes.patch`) and then applying it with `patch` (e.g., `patch -p0 < my_changes.patch` or `patch -p1 < my_changes.patch` if the patch paths include a base directory).
UNDERSTANDING <I>-P</I> (STRIP)
The `-p NUM` option tells patch how many leading directory components to ignore from the filenames listed in the patch file. If a patch file lists `a/src/main.c` and your `src/main.c` is in the current directory, you'd use `-p1` to strip `a/`. If the patch lists `src/main.c` and you are in the parent directory of `src/`, you'd use `-p0`.
REJECT FILES (<I>.REJ</I>)
When patch encounters a hunk (a block of changes) it cannot apply cleanly, it skips that hunk and writes the failed portion to a "reject" file, typically named by adding .rej to the original filename (e.g., `main.c.rej`). These files contain the original line numbers from the patch and the content of the failed hunk, requiring manual intervention to apply the changes.
HISTORY
The patch utility was originally written by Larry Wall (the creator of Perl) in 1985. It quickly became a standard and indispensable tool in Unix-like operating systems.
Before the widespread adoption of distributed version control systems like Git and Mercurial, patch was the primary method for sharing and applying changes to source code in open-source projects. Developers would generate diff files and email them to maintainers or upload them to bug trackers.
Despite the rise of modern VCS, patch remains relevant for applying simple fixes, handling patches generated outside of a VCS, or when working in environments where full VCS installations are not practical. Its robust handling of various diff formats contributed to its enduring utility.