Introduction

diff and patch are exceptionally useful tools if you want to discover the differences between two files.

The patch program allows you to take the output from diff and make those changes to the original files located on another system.

This tutorial will concentrate on this use case although it can be used for other purposes as well. For this tutorial we will use a css file as an example. We will start with this style.css

body{
        font-family:    Arial, Helvetica, sans-serif;
        font-size:      14px;
        color:          #555;
        background:     #FFF;
}

.pull-top{
        padding-top:    50px;
}

.header {
        color:          #FFF;
        border:         solid;
}

We will also need a second copy of this file called style-v2.css. Once you have these two files edit the second one and change the padding-top: 50px; element to padding-top: 100px; We are keeping the differences small in order to make the results easily readable.

Diff

The basic usage of diff is diff [options] oldfile newfile. This will output to the screen. To send the output to a 3rd file you need to redirect it using >filename.diff.

The options we will look at here are -r, -u, and -y.

The -u option means output in unified format. This format is more compact and misses out certain redundant information such as context lines. It also groups things like line numbers. There has been lots of debate over the two main types of output. However unified for small patches is easier to read so we will concentrate on using this format here.

The -r option is for recursively executing diff through a directory structure if you want to diff multiple files.

The -y option puts the differences side by side.

Examples.

If you simply want to see what the differences are between two files then use the -y option diff -y style.css style-v2.css
The output for our examples would be

[root@plesk diff]# diff -y style.css style-v2.css
body{                                                           body{
        font-family:    Arial, Helvetica, sans-serif;                   font-family:    Arial, Helvetica, sans-serif;
        font-size:      14px;                                           font-size:      14px;
        color:          #555;                                           color:          #555;
        background:     #FFF;                                           background:     #FFF;
}                                                               }


.pull-top{                                                      .pull-top{
        padding-top:    50px;                                 |         padding-top:    100px;
}                                                               }

.header {                                                       .header {
        color:          #FFF;                                           color:          #FFF;
        border:         solid;                                          border:         solid;
}                                                               }

In the second column you should be able to see the pipe symbol | next to the line that has changed in the second file. If the file is long and has scrolled off screen you can pipe the output to less so you can scroll back and forward. diff -y style.css style-v2.css | less

Tip

Sometimes you may want the pipe symbol to stand out so that it is clear. If you use this grep addition diff -y style.css style-v2.css | grep --color -E '\||$' It will colorize the | symbol so you can spot it more easily.

Using Diff for creating patch files

If we now use the -u option diff -u style.css style-v2.css you can now see it displays the lines to change with a + and - next to them but also shows three lines before and three lines after.

[root@plesk diff]# diff -u style.css style-v2.css
--- style.css   2015-09-14 04:26:53.000000000 +0200
+++ style-v2.css        2015-09-14 04:27:00.000000000 +0200
@@ -6,7 +6,7 @@
 }

 .pull-top{
-       padding-top:    50px;
+       padding-top:    100px;
 }

 .header {

These additional three lines are to give context to the file so that patch can check for improved accuracy. If you want to reduce the number of lines you can use -U2 for example. To increase the number of lines you could use -U5.
The first two lines are describing the files we are comparing. The lines between the @@ -l,n +l,n @@ is a description of the line number and how many lines are affected or are context lines. This is in the format of @@ -l,n +l,n @@. The l means line number and the n means number of lines affected. There are seven lines affected by this diff. Three before and three after, plus the line we modified, and it starts at line 6 in the source file.

We now need to save this to a patch file for use in the next section of this tutorial. To do this redirect the output to a file diff -u style.css style-v2.css >style.css.patch

Patch

This section will show you how to apply a patch. Before we do that you need to know about the -b option. This creates a backup of the original file with a .orig extension. We will use the -b option in our examples.

Using the Patch command purely for our purposes as described above is straightforward. You would use this command patch -ub style.css <style.css.patch. When you do enter ls -l now you will see the following:

-rw-r--r--. 1 root root 185 Sep 14 04:35 style.css
-rw-r--r--. 1 root root 184 Sep 14 04:26 style.css.orig
-rw-r--r--. 1 root root 195 Sep 14 04:34 style.css.patch
-rw-r--r--. 1 root root 185 Sep 14 04:27 style-v2.css

To restore the original file you would now enter cp style.css.orig style.css.

Whole Directory Diffs

This is perhaps one of the most common uses for Diff and Patch. As an example, you are using V 1.0.3 of a large piece of software that is made up of thousands of files. The author fixes a number of bugs to release V 1.0.4. He has made changes in 23 files that are only minor. He now has two choices: either make you download all the files again and do a full reinstall or give you a list of 23 file edits you have to do 100% accurately. This is where diff reaches its full usefulness and power.

He will have a copy of V 1.0.3 files and a separate copy of his V 1.0.4 because he uses a decent version control system such as git. For this example he has a directory structure like this.

/src/
/src/archive/v1.0.2
/src/archive/v1.0.3
/src/current/v1.0.4

He would cd to the /src directory and issue this command:
diff -ur archive/v1.0.3 current/v1.0.4 >v1.0.4.patch

On your system you would cd to the install folder of this software and execute this command patch -s -p0 < v1.0.4.patch
The -s option tells patch to stay silent unless there is an error. The -p0 tells patch not to strip any leading directory names. This ensures that you are matching the folders like for like with the original. We are not using the -b option in this case because you will take a backup of the folder before applying the patch. This is very important as you may need to restore the old version quickly.