Next: , Previous: , Up: Comparing and Merging Files   [Contents][Index]

10 Merging with patch

patch takes comparison output produced by diff and applies the differences to a copy of the original file, producing a patched version. With patch, you can distribute just the changes to a set of files instead of distributing the entire file set; your correspondents can apply patch to update their copy of the files with your changes. patch automatically determines the diff format, skips any leading or trailing headers, and uses the headers to determine which file to patch. This lets your correspondents feed a mail message containing a difference listing directly to patch.

patch detects and warns about common problems like forward patches. It saves any patches that it could not apply. It can also maintain a patchlevel.h file to ensure that your correspondents apply diffs in the proper order.

patch accepts a series of diffs in its standard input, usually separated by headers that specify which file to patch. It applies diff hunks (see Hunks) one by one. If a hunk does not exactly match the original file, patch uses heuristics to try to patch the file as well as it can. If no approximate match can be found, patch rejects the hunk and skips to the next hunk. patch normally replaces each file f with its new version, putting reject hunks (if any) into ‘f.rej’.

See Invoking patch, for detailed information on the options to patch.


10.1 Selecting the patch Input Format

patch normally determines which diff format the patch file uses by examining its contents. For patch files that contain particularly confusing leading text, you might need to use one of the following options to force patch to interpret the patch file as a certain format of diff. The output formats listed here are the only ones that patch can understand.

-c
--context

context diff.

-e
--ed

ed script.

-n
--normal

normal diff.

-u
--unified

unified diff.


10.2 Revision Control

If a nonexistent input file is under a revision control system supported by patch, patch normally asks the user whether to get (or check out) the file from the revision control system. Patch currently supports RCS, ClearCase and SCCS. Under RCS and SCCS, patch also asks when the input file is read-only and matches the default version in the revision control system.

The --get=num (-g num) option affects access to files under supported revision control systems. If num is positive, patch gets the file without asking the user; if zero, patch neither asks the user nor gets the file; and if negative, patch asks the user before getting the file. The default value of num is given by the value of the PATCH_GET environment variable if it is set; if not, the default value is zero if patch is conforming to POSIX, negative otherwise. See patch and the POSIX Standard.

The choice of revision control system is unaffected by the VERSION_CONTROL environment variable (see Backup File Names).


10.3 Applying Imperfect Patches

patch tries to skip any leading text in the patch file, apply the diff, and then skip any trailing text. Thus you can feed a mail message directly to patch, and it should work. If the entire diff is indented by a constant amount of white space, patch automatically ignores the indentation. If a context diff contains trailing carriage return on each line, patch automatically ignores the carriage return. If a context diff has been encapsulated by prepending ‘-  to lines beginning with ‘-’ as per Internet RFC 934, patch automatically unencapsulates the input.

However, certain other types of imperfect input require user intervention or testing.


10.3.1 Applying Patches with Changed White Space

Sometimes mailers, editors, or other programs change spaces into tabs, or vice versa. If this happens to a patch file or an input file, the files might look the same, but patch will not be able to match them properly. If this problem occurs, use the -l or --ignore-white-space option, which makes patch compare blank characters (i.e. spaces and tabs) loosely so that any nonempty sequence of blanks in the patch file matches any nonempty sequence of blanks in the input files. Non-blank characters must still match exactly. Each line of the context must still match a line in the input file.


10.3.2 Applying Reversed Patches

Sometimes people run diff with the new file first instead of second. This creates a diff that is “reversed”. To apply such patches, give patch the --reverse (-R) option. patch then attempts to swap each hunk around before applying it. Rejects come out in the swapped format.

Often patch can guess that the patch is reversed. If the first hunk of a patch fails, patch reverses the hunk to see if it can apply it that way. If it can, patch asks you if you want to have the -R option set; if it can’t, patch continues to apply the patch normally. This method cannot detect a reversed patch if it is a normal diff and the first command is an append (which should have been a delete) since appends always succeed, because a null context matches anywhere. But most patches add or change lines rather than delete them, so most reversed normal diffs begin with a delete, which fails, and patch notices.

If you apply a patch that you have already applied, patch thinks it is a reversed patch and offers to un-apply the patch. This could be construed as a feature. If you did this inadvertently and you don’t want to un-apply the patch, just answer ‘n’ to this offer and to the subsequent “apply anyway” question—or type C-c to kill the patch process.


10.3.3 Helping patch Find Inexact Matches

For context diffs, and to a lesser extent normal diffs, patch can detect when the line numbers mentioned in the patch are incorrect, and it attempts to find the correct place to apply each hunk of the patch. As a first guess, it takes the line number mentioned in the hunk, plus or minus any offset used in applying the previous hunk. If that is not the correct place, patch scans both forward and backward for a set of lines matching the context given in the hunk.

First patch looks for a place where all lines of the context match. If it cannot find such a place, and it is reading a context or unified diff, and the maximum fuzz factor is set to 1 or more, then patch makes another scan, ignoring the first and last line of context. If that fails, and the maximum fuzz factor is set to 2 or more, it makes another scan, ignoring the first two and last two lines of context are ignored. It continues similarly if the maximum fuzz factor is larger.

The --fuzz=lines (-F lines) option sets the maximum fuzz factor to lines. This option only applies to context and unified diffs; it ignores up to lines lines while looking for the place to install a hunk. Note that a larger fuzz factor increases the odds of making a faulty patch. The default fuzz factor is 2; there is no point to setting it to more than the number of lines of context in the diff, ordinarily 3.

If patch cannot find a place to install a hunk of the patch, it writes the hunk out to a reject file (see Reject File Names, for information on how reject files are named). It writes out rejected hunks in context format no matter what form the input patch is in. If the input is a normal or ed diff, many of the contexts are simply null. The line numbers on the hunks in the reject file may be different from those in the patch file: they show the approximate location where patch thinks the failed hunks belong in the new file rather than in the old one.

If the --verbose option is given, then as it completes each hunk patch tells you whether the hunk succeeded or failed, and if it failed, on which line (in the new file) patch thinks the hunk should go. If this is different from the line number specified in the diff, it tells you the offset. A single large offset may indicate that patch installed a hunk in the wrong place. patch also tells you if it used a fuzz factor to make the match, in which case you should also be slightly suspicious.

patch cannot tell if the line numbers are off in an ed script, and can only detect wrong line numbers in a normal diff when it finds a change or delete command. It may have the same problem with a context diff using a fuzz factor equal to or greater than the number of lines of context shown in the diff (typically 3). In these cases, you should probably look at a context diff between your original and patched input files to see if the changes make sense. Compiling without errors is a pretty good indication that the patch worked, but not a guarantee.

A patch against an empty file applies to a nonexistent file, and vice versa. See Creating and Removing Files.

patch usually produces the correct results, even when it must make many guesses. However, the results are guaranteed only when the patch is applied to an exact copy of the file that the patch was generated from.


10.3.4 Predicting what patch will do

It may not be obvious in advance what patch will do with a complicated or poorly formatted patch. If you are concerned that the input might cause patch to modify the wrong files, you can use the --dry-run option, which causes patch to print the results of applying patches without actually changing any files. You can then inspect the diagnostics generated by the dry run to see whether patch will modify the files that you expect. If the patch does not do what you want, you can modify the patch (or the other options to patch) and try another dry run. Once you are satisfied with the proposed patch you can apply it by invoking patch as before, but this time without the --dry-run option.


10.4 Creating and Removing Files

Sometimes when comparing two directories, a file may exist in one directory but not the other. If you give diff the --new-file (-N) option, or if you supply an old or new file that is named /dev/null or is empty and is dated the Epoch (1970-01-01 00:00:00 UTC), diff outputs a patch that adds or deletes the contents of this file. When given such a patch, patch normally creates a new file or removes the old file. However, when conforming to POSIX (see patch and the POSIX Standard), patch does not remove the old file, but leaves it empty. The --remove-empty-files (-E) option causes patch to remove output files that are empty after applying a patch, even if the patch does not appear to be one that removed the file.

If the patch appears to create a file that already exists, patch asks for confirmation before applying the patch.


10.5 Updating Timestamps on Patched Files

When patch updates a file, it normally sets the file’s last-modified timestamp to the current time of day. If you are using patch to track a software distribution, this can cause make to incorrectly conclude that a patched file is out of date. For example, if syntax.c depends on syntax.y, and patch updates syntax.c and then syntax.y, then syntax.c will normally appear to be out of date with respect to syntax.y even though its contents are actually up to date.

The --set-utc (-Z) option causes patch to set a patched file’s modification and access times to the timestamps given in context diff headers. If the context diff headers do not specify a time zone, they are assumed to use Coordinated Universal Time (UTC, often known as GMT).

The --set-time (-T) option acts like -Z or --set-utc, except that it assumes that the context diff headers’ timestamps use local time instead of UTC. This option is not recommended, because patches using local time cannot easily be used by people in other time zones, and because local timestamps are ambiguous when local clocks move backwards during daylight-saving time adjustments. If the context diff headers specify a time zone, this option is equivalent to --set-utc (-Z).

patch normally refrains from setting a file’s timestamps if the file’s original last-modified timestamp does not match the time given in the diff header, of if the file’s contents do not exactly match the patch. However, if the --force (-f) option is given, the file’s timestamps are set regardless.

Due to the limitations of the current diff format, patch cannot update the times of files whose contents have not changed. Also, if you set file timestamps to values other than the current time of day, you should also remove (e.g., with ‘make clean’) all files that depend on the patched files, so that later invocations of make do not get confused by the patched files’ times.


10.6 Multiple Patches in a File

If the patch file contains more than one patch, and if you do not specify an input file on the command line, patch tries to apply each patch as if they came from separate patch files. This means that it determines the name of the file to patch for each patch, and that it examines the leading text before each patch for file names and prerequisite revision level (see Tips for Making and Using Patches, for more on that topic).

patch uses the following rules to intuit a file name from the leading text before a patch. First, patch takes an ordered list of candidate file names as follows:

Then patch selects a file name from the candidate list as follows:

To determine the best of a nonempty list of file names, patch first takes all the names with the fewest path name components; of those, it then takes all the names with the shortest basename; of those, it then takes all the shortest names; finally, it takes the first remaining name.

See patch and the POSIX Standard, to see whether patch is conforming to POSIX.


10.7 Applying Patches in Other Directories

The --directory=directory (-d directory) option to patch makes directory directory the current directory for interpreting both file names in the patch file, and file names given as arguments to other options (such as -B and -o). For example, while in a mail reading program, you can patch a file in the /usr/src/emacs directory directly from a message containing the patch like this:

| patch -d /usr/src/emacs

Sometimes the file names given in a patch contain leading directories, but you keep your files in a directory different from the one given in the patch. In those cases, you can use the --strip=number (-pnumber) option to set the file name strip count to number. The strip count tells patch how many slashes, along with the directory names between them, to strip from the front of file names. A sequence of one or more adjacent slashes is counted as a single slash. By default, patch strips off all leading directories, leaving just the base file names.

For example, suppose the file name in the patch file is /gnu/src/emacs/etc/NEWS. Using -p0 gives the entire file name unmodified, -p1 gives gnu/src/emacs/etc/NEWS (no leading slash), -p4 gives etc/NEWS, and not specifying -p at all gives NEWS.

patch looks for each file (after any slashes have been stripped) in the current directory, or if you used the -d directory option, in that directory.


10.8 Backup Files

Normally, patch creates a backup file if the patch does not exactly match the original input file, because in that case the original data might not be recovered if you undo the patch with ‘patch -R’ (see Applying Reversed Patches). However, when conforming to POSIX, patch does not create backup files by default. See patch and the POSIX Standard.

The --backup (-b) option causes patch to make a backup file regardless of whether the patch matches the original input. The --backup-if-mismatch option causes patch to create backup files for mismatches files; this is the default when not conforming to POSIX. The --no-backup-if-mismatch option causes patch to not create backup files, even for mismatched patches; this is the default when conforming to POSIX.

When backing up a file that does not exist, an empty, unreadable backup file is created as a placeholder to represent the nonexistent file.


10.9 Backup File Names

Normally, patch renames an original input file into a backup file by appending to its name the extension ‘.orig’, or ‘~’ if using ‘.orig’ would make the backup file name too long.1 The -z backup-suffix or --suffix=backup-suffix option causes patch to use backup-suffix as the backup extension instead.

Alternately, you can specify the extension for backup files with the SIMPLE_BACKUP_SUFFIX environment variable, which the options override.

patch can also create numbered backup files the way GNU Emacs does. With this method, instead of having a single backup of each file, patch makes a new backup file name each time it patches a file. For example, the backups of a file named sink would be called, successively, sink.~1~, sink.~2~, sink.~3~, etc.

The -V backup-style or --version-control=backup-style option takes as an argument a method for creating backup file names. You can alternately control the type of backups that patch makes with the PATCH_VERSION_CONTROL environment variable, which the -V option overrides. If PATCH_VERSION_CONTROL is not set, the VERSION_CONTROL environment variable is used instead. Please note that these options and variables control backup file names; they do not affect the choice of revision control system (see Revision Control).

The values of these environment variables and the argument to the -V option are like the GNU Emacs version-control variable (see Backup Names in The GNU Emacs Manual, for more information on backup versions in Emacs). They also recognize synonyms that are more descriptive. The valid values are listed below; unique abbreviations are acceptable.

t
numbered

Always make numbered backups.

nil
existing

Make numbered backups of files that already have them, simple backups of the others. This is the default.

never
simple

Always make simple backups.

You can also tell patch to prepend a prefix, such as a directory name, to produce backup file names. The --prefix=prefix (-B prefix) option makes backup files by prepending prefix to them. The --basename-prefix=prefix (-Y prefix) prepends prefix to the last file name component of backup file names instead; for example, -Y ~ causes the backup name for dir/file.c to be dir/~file.c. If you use either of these prefix options, the suffix-based options are ignored.

If you specify the output file with the -o option, that file is the one that is backed up, not the input file.

Options that affect the names of backup files do not affect whether backups are made. For example, if you specify the --no-backup-if-mismatch option, none of the options described in this section have any affect, because no backups are made.


10.10 Reject File Names

The names for reject files (files containing patches that patch could not find a place to apply) are normally the name of the output file with ‘.rej’ appended (or ‘#’ if using ‘.rej’ would make the backup file name too long).

Alternatively, you can tell patch to place all of the rejected patches in a single file. The -r reject-file or --reject-file=reject-file option uses reject-file as the reject file name.


10.11 Messages and Questions from patch

patch can produce a variety of messages, especially if it has trouble decoding its input. In a few situations where it’s not sure how to proceed, patch normally prompts you for more information from the keyboard. There are options to produce more or fewer messages, to have it not ask for keyboard input, and to affect the way that file names are quoted in messages.

patch exits with status 0 if all hunks are applied successfully, 1 if some hunks cannot be applied, and 2 if there is more serious trouble. When applying a set of patches in a loop, you should check the exit status, so you don’t apply a later patch to a partially patched file.


10.11.1 Controlling the Verbosity of patch

You can cause patch to produce more messages by using the --verbose option. For example, when you give this option, the message ‘Hmm...’ indicates that patch is reading text in the patch file, attempting to determine whether there is a patch in that text, and if so, what kind of patch it is.

You can inhibit all terminal output from patch, unless an error occurs, by using the -s, --quiet, or --silent option.


10.11.2 Inhibiting Keyboard Input

There are two ways you can prevent patch from asking you any questions. The --force (-f) option assumes that you know what you are doing. It causes patch to do the following:

  • Skip patches that do not contain file names in their headers.
  • Patch files even though they have the wrong version for the ‘Prereq:’ line in the patch;
  • Assume that patches are not reversed even if they look like they are.

The --batch (-t) option is similar to -f, in that it suppresses questions, but it makes somewhat different assumptions:

  • Skip patches that do not contain file names in their headers (the same as -f).
  • Skip patches for which the file has the wrong version for the ‘Prereq:’ line in the patch;
  • Assume that patches are reversed if they look like they are.

10.11.3 patch Quoting Style

When patch outputs a file name in a diagnostic message, it can format the name in any of several ways. This can be useful to output file names unambiguously, even if they contain punctuation or special characters like newlines. The --quoting-style=word option controls how names are output. The word should be one of the following:

literal

Output names as-is.

shell

Quote names for the shell if they contain shell metacharacters or would cause ambiguous output.

shell-always

Quote names for the shell, even if they would normally not require quoting.

c

Quote names as for a C language string.

escape

Quote as with ‘c’ except omit the surrounding double-quote characters.

You can specify the default value of the --quoting-style option with the environment variable QUOTING_STYLE. If that environment variable is not set, the default value is ‘shell’, but this default may change in a future version of patch.


10.12 patch and the POSIX Standard

If you specify the --posix option, or set the POSIXLY_CORRECT environment variable, patch conforms more strictly to the POSIX standard, as follows:


10.13 GNU patch and Traditional patch

The current version of GNU patch normally follows the POSIX standard. See patch and the POSIX Standard, for the few exceptions to this general rule.

Unfortunately, POSIX redefined the behavior of patch in several important ways. You should be aware of the following differences if you must interoperate with traditional patch, or with GNU patch version 2.1 and earlier.


Footnotes

(1)

A coding error in GNU patch version 2.5.4 causes it to always use ‘~’, but this should be fixed in the next release.


Next: , Previous: , Up: Comparing and Merging Files   [Contents][Index]