24

What's the difference between patch -p0 and patch -p1?

Is there any difference at all?

chrisjlee
  • 8,283
  • 16
  • 49
  • 54

3 Answers3

30

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.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
  • 2
    This has confused me for so long. Why is the behavior of no subdirectories different from -p0? I've always assumed that -p0 was default, so I always had issues if it was supposed to be p0 – Brydon Gibson Sep 26 '19 at 15:34
  • @BrydonGibson I suspect that originally the idea was that the patch author could indifferently write `diff old/foo new/foo >my.patch` or `diff ../old/foo foo >my.patch` or `diff foo.old foo >my.patch` and the user could apply it with `patch – Gilles 'SO- stop being evil' Sep 26 '19 at 16:23
  • 1
    Another instance of `man` pages failing to be useful, at least for `GNU/patch`. Thanks for the clear explanation! – brainplot Jan 29 '20 at 21:35
  • Thank you very much, the man page indeed explains it too cryptically – rkok Sep 09 '22 at 09:13
  • I don’t get why they are calling it a “_filename_,” that is a “_file **path**_.” It strips the first N segments of the file paths specified in the `.diff` file. – Константин Ван Mar 19 '23 at 06:47
16

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 gives

 u/howard/src/blurfl/blurfl.c

without the leading slash, -p4 gives

 blurfl/blurfl.c
Stéphane Gimenez
  • 28,527
  • 3
  • 76
  • 87
7

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.