How to create and use a patch in Linux

Creating a Patch File:

diff -Naur olddir newdir > new-patch
- or -
diff -Naur oldfile newfile >new-patch

A Note concerning Patch and the number of Directory Levels used:

Try to make sure when creating a patchfile that you have the same number of directories levels for both the olddir path and newdir path. For Ex:
--- old/modules/pcitable	Mon Sep 27 11:03:56 1999
+++ new/modules/pcitable	Tue Dec 19 20:05:41 2000
The above diff would work ok as a patch.
--- old/try1/other/modules/pcitable	Mon Sep 27 11:03:56 1999
+++ new/modules/pcitable	Tue Dec 19 20:05:41 2000
You may have problems with the above diff working as a patch. Note that the first one has 4 directory levels mentioned and the 2nd one has only two. I would suggest modifying the --- and +++ lines to make the directory structure in both to be the same number of levels deep.

Using the Patch Command:

patch -p0 <new-patch
patch -p1 <new-patch
Which one of the above patch commands you use depends on your current working directory.

Levels in the Patch Command (-p0 or -p1?):

The -p option will optionally strip off directory levels from the patchfile. For Ex: if you have a patchfile with a header as such:
--- old/modules/pcitable	Mon Sep 27 11:03:56 1999
+++ new/modules/pcitable	Tue Dec 19 20:05:41 2000
Using a -p0 will expect, from your current working directory, to find a subdirectory called "new", then "modules" below that, then the "pcitable" file below that.

Using a -p1 will strip off the 1st level from the path and will expect to find (from your current working directory) a directory called "modules", then a file called "pcitable". Patch will ignore the "new" directory mentioned in the header of the patchfile.

Using a -p2 will strip of the first two levels from the path. Patch will expect to find "pcitable" in the current working directory. Patch will ignore the "new" and "module" directories mentioned in the header of the patchfile.

Using a -p3 in this example would not be a good thing. Patch probably wouldn't patch anything.

...

Applying a Patch:

Just change to the correct directory and give the patch command (see
Using the Patch Command above). Usually is:
cd /usr/src/linux
patch -p0 <new-patch
unless the patchfile has "linux" as part of the directory structure on the +++ line, in that case issue the patch command with the -p1 as follows:
patch -p1 <new-patch

Patch Header:

In these examples a patch header begins with the two lines that begin with a --- and +++. This would indicate which filename to begin processing.

Multiple Patches in a Patchfile:

A patchfile can have multiple sections, each beginning with the --- / +++ headers mentioned above. So a single patchfile can actually modify several files. If you are reviewing a patchfile be sure to search for every instance of --- throughout the patchfile to see all the different files it patches.

An Example of one method to browse a patchfile:

less /tmp/file-patch <ENTER>
/--- <ENTER>
n
n
n
Note that the "/" invokes the search function in less, and each time you press "n" less will search for the next matching searchstring.

Hunks:

A hunk is a section to be patched. A hunk usually begins and ends with lines that don't need any changes, they are just mentioned so that Patch can find the appropriate place in the files to be patched. Hunk in these examples begins with a double at symbol (@@) and ends when either a new hunk starts or it finds a new patch header. Here's an example of a hunk:
@@ -1,4 +1,6 @@
 0x0e11	0xae10	"cpqarray"	"Compaq|Smart-2/P RAID Controller"
+0x1000	0x0010	"cpqarray"	"Compaq|Integrated Array Controller"
+0x1011	0x0046	"cpqarray"	"Compaq|Smart-2/P RAID Controller"
 0x0e11	0xae32	"tlan"	"Compaq|Netelligent 10/100"
 0x0e11	0xae34	"tlan"	"Compaq|Netelligent 10"
 0x0e11	0xae35	"tlan"	"Compaq|Integrated NetFlex-3/P"

Indentation in a Hunk:

In these examples you will notice that each hunk has been indented so that the text does not occupy the first column. In these examples Patch uses the first column in each patch to list the lines to be added or removed.

The First Column of a Hunk (+, -, and a blank):

The + would indicate that this particular line is to be added.

The - would indicate that this particular line is to be removed.

A line with neither a plus or minus would indicate that this particular line of code is just a reference point.

An Example Patchfile:

diff -u old/modules/pcitable new/modules/pcitable
--- old/modules/pcitable	Mon Sep 27 11:03:56 1999
+++ new/modules/pcitable	Tue Dec 19 20:05:41 2000
@@ -1,4 +1,6 @@
 0x0e11	0xae10	"cpqarray"	"Compaq|Smart-2/P RAID Controller"
+0x1000	0x0010	"cpqarray"	"Compaq|Integrated Array Controller"
+0x1011	0x0046	"cpqarray"	"Compaq|Smart-2/P RAID Controller"
 0x0e11	0xae32	"tlan"	"Compaq|Netelligent 10/100"
 0x0e11	0xae34	"tlan"	"Compaq|Netelligent 10"
 0x0e11	0xae35	"tlan"	"Compaq|Integrated NetFlex-3/P"
@@ -21,6 +23,7 @@
 0x1000	0x000f	"ncr53c8xx"	"Symbios|53c875"
 0x1000	0x0012	"ncr53c8xx"	"Symbios|53c895a"
 0x1000	0x008f	"ncr53c8xx"	"Symbios|53c875J"
+0x1000	0x000a	"sym53c8xx"	"Symbios|53c1510"
 0x1000	0x0701	"yellowfin"	"Symbios|83C885 gigabit ethernet"
 0x1000	0x0702	"yellowfin"	"Symbios|Yellowfin G-NIC gigabit ethernet"
 0x1011	0x0001	"tulip"	"DEC|DECchip 21050"
--- old/usr/share/kudzu/pcitable	Sun Sep 26 17:11:23 1999
+++ new/usr/share/kudzu/pcitable	Tue Dec 19 20:05:41 2000
@@ -15,6 +15,8 @@
 0x0e11	0x3034	"unknown"	"Compaq|QVision 1280/p"
 0x0e11	0x4000	"unknown"	"Compaq|4000 [Triflex]"
 0x0e11	0xa0f3	"ignore"	"Compaq|Triflex PCI to ISA Bridge"
+0x1000	0x0010	"cpqarray"	"Compaq|Integrated Array Controller"
+0x1011	0x0046	"cpqarray"	"Compaq|Smart-2/P RAID Controller"
 0x0e11	0xae10	"cpqarray"	"Compaq|Smart-2/P RAID Controller"
 0x0e11	0xae29	"unknown"	"Compaq|MIS-L"
 0x0e11	0xae2a	"unknown"	"Compaq|MPC"
@@ -46,6 +48,7 @@
 0x1000	0x000f	"ncr53c8xx"	"Symbios|53c875"
 0x1000	0x0012	"ncr53c8xx"	"Symbios|53c895a"
 0x1000	0x008f	"ncr53c8xx"	"Symbios|53c875J"
+0x1000	0x000a	"sym53c8xx"	"Symbios|53c1510"
 0x1000	0x0701	"yellowfin"	"Symbios|83C885 gigabit ethernet"
 0x1000	0x0702	"yellowfin"	"Symbios|Yellowfin G-NIC gigabit ethernet"
 0x1000	0x0901	"unknown"	"Symbios|61C102"

Analyzing the above Example:

This example was created using the following diff command:
diff -u old/modules/pcitable new/modules/pcitable
However, now I would probably only use the -Naur options instead of just -u. This example modifies two files: new/modules/pcitable, and new/usr/share/kudzu/pcitable.

The first patch header has two hunks. These particular hunks are adding 2 lines and 1 line respectively.


1