What's the difference between patch -p0 and patch -p1?
Is there any difference at all?
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:
-pnumor--strip=numStrip 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.csetting
-p0gives the entire file name unmodified,-p1givesu/howard/src/blurfl/blurfl.cwithout the leading slash,
-p4givesblurfl/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.