When patching what's the difference between arguments -p0 and -p1?
The most common way to create a patch is to run the diff
command or some version control's built-in diff
-like command. Sometimes, you're just comparing two files, and you run diff
like this:
diff -u version_by_alice.txt version_by_bob.txt >alice_to_bob.patch
Then you get a patch that contains changes for one file and doesn't contain a file name at all. When you apply that patch, you need to specify which file you want to apply it to:
patch <alice_to_bob.patch version2_by_alice.txt
Often, you're comparing two versions of a whole multi-file project contained in a directory. A typical invocation of diff
looks like this:
diff -ru old_version new_version >some.patch
Then the patch contains file names, given in header lines like diff -ru old_version/dir/file new_version/dir/file
. You need to tell patch
to strip the prefix (old_version
or new_version
) from the file name. That's what -p1
means: strip one level of directory.
Sometimes, the header lines in the patch contain the file name directly with no lead-up. This is common with version control systems; for example cvs diff
produces header lines that look like diff -r1.42 foo
. Then there is no prefix to strip, so you must specify -p0
.
In the special case when there are no subdirectories in the trees that you're comparing, no -p
option is necessary: patch
will discard all the directory part of the file names. But most of the time, you do need either -p0
or -p1
, depending on how the patch was produced.
From the man:
-pnum
or--strip=num
Strip the smallest prefix containing num leading slashes from each file name found in the patch file. A sequence of one or more adjacent slashes is counted as a single slash. This controls how file names found in the patch file are treated, in case you keep your files in a different directory than the person who sent out the patch. For example, supposing the file name in the patch file was:/u/howard/src/blurfl/blurfl.c
setting
-p0
gives the entire file name unmodified,-p1
givesu/howard/src/blurfl/blurfl.c
without the leading slash,
-p4
givesblurfl/blurfl.c
The difference is that the number after -p
would specify the number of path components that would be removed.
Say we have a path /Barack/Obama
. Executing a patch on it with the -p0
argument will treat the path as is:
/Barack/Obama
But we can trim the path while patching:
-p1
will remove the root slash (note that it will just be Barack now, without a slash left to it):
Barack/Obama
-p2
will remove Barack (and adjacent right slash):
Obama
To expand on the "why" of this patch
behavior, read this thread.