in reply to
submitting a patch for a directory
The situation ( file/directory tree )
$ tree -f -a .
.
|-- ./Foo
| `-- ./Foo/one.txt
|-- ./Foo-new
| |-- ./Foo-new/one.txt
| `-- ./Foo-new/two.txt
`-- ./Foo-old
`-- ./Foo-old/one.txt
3 directories, 4 files
Foo is the original directory (CGI.pm-3.59)
Foo-old is the backup pristine copy (CGI.pm-3.59-old)
Foo-new is thing you've edited that you generate the patch from (CGI.pm-3.59-new)
Creating a new patch ( Foo-new.patch, CGI.pm-3.59-new.patch )
$ diff -Npurd Foo-old Foo-new > Foo-new.patch
What the switches mean
- -N => --new-file Treat absent files as empty.
- -p => --show-c-function Show which C function each change is in.
- -u => -U NUM --unified=NUM Output NUM (default 3) lines of unified context.
- -r => --recursive Recursively compare any subdirectories found.
- -d => --minimal Try hard to find a smaller set of changes.
NOTE: If you're making a patch from a directory like CGI.pm-3.59, where you've used perl Makefile.PL && make, esp if using -N, you should clean up before making a patch, you should make realclean
What a patch looks like
$ cat Foo-new.patch
diff -Npurd Foo-old/one.txt Foo-new/one.txt
--- Foo-old/one.txt 2012-08-16 08:21:35.609375000 -0700
+++ Foo-new/one.txt 2012-08-16 08:19:45.859375000 -0700
@@ -1 +1 @@
-hi there
+hello there
diff -Npurd Foo-old/two.txt Foo-new/two.txt
--- Foo-old/two.txt 1969-12-31 16:00:00.000000000 -0800
+++ Foo-new/two.txt 2012-08-16 08:19:25.500000000 -0700
@@ -0,0 +1 @@
+new file
Applying your new patch to Foo (CGI.pm-3.59), what the recipient of that patch would do, is first change working directory, then call patch
$ cd Foo
$ patch -p1 -i../Foo-new.patch
$ cd Foo
$ patch -p1 -i../Foo-new.patch
patching file one.txt
patching file two.txt
-p1 means ignore the first path part, ignore the bold parts
--- Foo-old/two.txt 1969-12-31 16:00:00.000000000 -0800
+++ Foo-new/two.txt 2012-08-16 08:19:25.500000000 -0700
It also means don't create a Foo-new directory :)
If you used -p0 (ignore no path parts) the patching would fail in two ways, it wouldn't find one.txt, and it would create a Foo-new directory
$ patch -p0 -i../Foo-new.patch
can't find file to patch at input line 4
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff -Npurd Foo-old/one.txt Foo-new/one.txt
|--- Foo-old/one.txt 2012-08-16 08:21:35.609375000 -0700
|+++ Foo-new/one.txt 2012-08-16 08:19:45.859375000 -0700
--------------------------
File to patch:
Skip this patch? [y]
Skipping patch.
1 out of 1 hunk ignored
patching file Foo-old/two.txt
$ tree -f -a .
.
|-- ./Foo-old
| `-- ./Foo-old/two.txt
`-- ./one.txt
1 directory, 2 files
For best patching experience
Always use relative paths for diff -Npurd diffolddir newdir
Always use the p1 or p0 option, otherwise patch will ignore all directories/patch the wrong file
To re-create my original situation, to create files and directories out of a patch, first produce the patch
diff -Npurd emptyDir tmpFoo > tmpFoo.patch
The new patch tmpFoo.patch looks like
diff -Npurd emptyDir/Foo/one.txt tmpFoo/Foo/one.txt
--- emptyDir/Foo/one.txt 1969-12-31 16:00:00.000000000 -0800
+++ tmpFoo/Foo/one.txt 2012-08-16 08:21:35.609375000 -0700
@@ -0,0 +1 @@
+hi there
diff -Npurd emptyDir/Foo-new/one.txt tmpFoo/Foo-new/one.txt
--- emptyDir/Foo-new/one.txt 1969-12-31 16:00:00.000000000 -0800
+++ tmpFoo/Foo-new/one.txt 2012-08-16 08:19:45.859375000 -0700
@@ -0,0 +1 @@
+hello there
diff -Npurd emptyDir/Foo-new/two.txt tmpFoo/Foo-new/two.txt
--- emptyDir/Foo-new/two.txt 1969-12-31 16:00:00.000000000 -0800
+++ tmpFoo/Foo-new/two.txt 2012-08-16 08:19:25.500000000 -0700
@@ -0,0 +1 @@
+new file
diff -Npurd emptyDir/Foo-old/one.txt tmpFoo/Foo-old/one.txt
--- emptyDir/Foo-old/one.txt 1969-12-31 16:00:00.000000000 -0800
+++ tmpFoo/Foo-old/one.txt 2012-08-16 08:21:35.609375000 -0700
@@ -0,0 +1 @@
+hi there
Then apply the patch in your new working directory tmp2Foo
$ cd tmp2Foo
$ patch -i ../tmpFoo.patch
The next patch would create the file one.txt,
which already exists! Assume -R? [n]
Apply anyway? [n]
Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file one.txt.rej
The next patch would create the file one.txt,
which already exists! Assume -R? [n]
Apply anyway? [n]
Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file one.txt.rej
The next patch would create the file two.txt,
which already exists! Assume -R? [n]
Apply anyway? [n]
Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file two.txt.rej
The next patch would create the file one.txt,
which already exists! Assume -R? [n]
Apply anyway? [n]
Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file one.txt.rej
$ tree -f -a .
.
|-- ./one.txt
|-- ./one.txt.rej
|-- ./two.txt
`-- ./two.txt.rej
0 directories, 4 files
Oh noes, a mistake! I forgot to include the -p1 switch, and no directories were created! Trying again with -p1
$ patch -p1 -i ../tmpFoo.patch
patching file Foo/one.txt
patching file Foo-new/one.txt
patching file Foo-new/two.txt
patching file Foo-old/one.txt
$ tree -f -a .
.
|-- ./Foo
| `-- ./Foo/one.txt
|-- ./Foo-new
| |-- ./Foo-new/one.txt
| `-- ./Foo-new/two.txt
`-- ./Foo-old
`-- ./Foo-old/one.txt
3 directories, 4 files
Hooray! Hmm, I'll try p0 in the same directory
$ patch -p0 -i ../tmpFoo.patch
patching file tmpFoo/Foo/one.txt
patching file tmpFoo/Foo-new/one.txt
patching file tmpFoo/Foo-new/two.txt
patching file tmpFoo/Foo-old/one.txt
$ tree -f -a
.
|-- ./Foo
| `-- ./Foo/one.txt
|-- ./Foo-new
| |-- ./Foo-new/one.txt
| `-- ./Foo-new/two.txt
|-- ./Foo-old
| `-- ./Foo-old/one.txt
`-- ./tmpFoo
|-- ./tmpFoo/Foo
| `-- ./tmpFoo/Foo/one.txt
|-- ./tmpFoo/Foo-new
| |-- ./tmpFoo/Foo-new/one.txt
| `-- ./tmpFoo/Foo-new/two.txt
`-- ./tmpFoo/Foo-old
`-- ./tmpFoo/Foo-old/one.txt
7 directories, 8 files
Whoa, that worked also and it didn't interfere :) but I don't really need that extra tmpFoo, now to get rid of it without rm -rfv -- from the same working directory
-Reversing a patch (just add -R to the command you used to apply the patch)
$ patch -p0 -R -i ../tmpFoo.patch
patching file tmpFoo/Foo/one.txt
patching file tmpFoo/Foo-new/one.txt
patching file tmpFoo/Foo-new/two.txt
patching file tmpFoo/Foo-old/one.txt
$ tree -f -a
.
|-- ./Foo
| `-- ./Foo/one.txt
|-- ./Foo-new
| |-- ./Foo-new/one.txt
| `-- ./Foo-new/two.txt
`-- ./Foo-old
`-- ./Foo-old/one.txt
3 directories, 4 files
See also http://perldoc.perl.org/5.14.0/perlhack.html#Patching, http://perldoc.perl.org/5.10.0/perlhack.html#Patching