11 April 2005 - 0:48The Patch Command and OSS
I have found patch files to be very helpful while using FreeBSD. Although I only use patch for altering program code, it could essentially be used in many other areas. Since not everyone is able to use CVS or Subversion because of skill level or have no write access to the repository, patch files are a basic, low level means of communicating changes to a particular file, without having to keep track of these changes yourself. This is especially important in code, since quick changes can quickly become out of hand. Patch files are also useful for the person implementing those changes. The patch file format that I currently use for tracking changes easily shows the differences between whole directory trees. This way you have a central location to view the changes that you’ve made. Another advantage is that patch automatically creates backup files for you so that if something goes wrong, you do not have to dig through the changes to fix the problem. This should get you started with using patch.
Problem
The main problem patch solves is tracking changes among files. It will work on essentially all text, from config files to program code. The patch command is not difficult to use which makes it very handy for tracking changes you make on data. Creating a patch file is a little different than actually using it, but the process is still not difficult.
Solution
First I will show the way I most commonly use patch; when there is a project folder that you wish to modify. First I assume there are files in the folder you wish to modify. I’ll call this folder project. The first step is to copy the original folder to a backup location so that you have copies of the unmodified sources:
cp -Rp project project-orig
Now the example file that I’m using is called project-orig/test_file.conf . The contents of project-orig/test_file.conf:
existing1 = 1 existing2 = 0 existing3 = 1
Now the modifications are shown here:
existing1 = 1 existing2 = 0 inserted1 = 1 existing3 = 1
Now make sure that you are OUTSIDE the project folder and can see both the modified project folder and the original. The commands to create the patch file:
diff -Naur project-orig project > change1.patch
The contents of the patch file change1.patch:
diff -Naur project-orig/test_file.conf project/test_file.conf --- project-orig/test_file.conf Sat Apr 9 19:41:12 2005 +++ project/test_file.conf Sat Apr 9 19:53:14 2005 @@ -1,3 +1,4 @@ existing1 = 1 existing2 = 0 +inserted1 = 1 existing3 = 1
How To Read The Diff File
There are a few important things to notice. First, I did not use the default diff options. With the options that I have specified, three deal with the nature of having multiple files, but the big change is the -u flag. That will show us a bit more information about the differences between the files than the default would. Next, you should notice that it shows the command that was used to compare the files. This is not the same command that we ran. Since we ran it recursively on the directory, this is the diff that was run on the single file in that directory. If we had other files with differences, another listing like you see above would be shown directly after that one.
Next you see the two files that are being compared. Diff uses + and - to distinguish between the new file and the original file respectively. The + and - symbols are used in the line location, as well as to show which file each line belongs to.
The line @@ -1,3 +1,4 @@ shows where the difference occurred. the first group of numbers -1,3 shows that this is the original file, the first line in the diff listing is on line 1 of the file, and the diff listing represents 3 lines of code in the original file.
The actual diff text comes next. Any line beginning with a space belongs to both files. Any line starting with a + or - only exists in that file. Since there are three lines beginning with a space, and one with a +, we can see that only three lines are being represented in the original file. We can also see that since there is one + line, there are four lines being represented in the new file.
Why Is This Important
You should always check your resulting patch file to make sure that it is correct, and that you will not accidentally leak sensitive information. Here is an extended example of our project diff file:
diff -Naur project-orig/db.conf project/db.conf --- project-orig/db.conf Sat Apr 9 20:39:54 2005 +++ project/db.conf Sat Apr 9 20:40:23 2005 @@ -1,4 +1,4 @@ server = localhost db = test_db -user = some_user -pass = some_pass +user = TheGillis +pass = super.secret.pw diff -Naur project-orig/test_file.conf project/test_file.conf --- project-orig/test_file.conf Sat Apr 9 20:41:04 2005 +++ project/test_file.conf Sat Apr 9 20:41:05 2005 @@ -1,3 +1,4 @@ existing1 = 1 existing2 = 0 +inserted1 = 1 existing3 = 1
Now this is very important. You should see that from the first diff that occurs between our new file db.conf there is some secret information in there. If you do not check your diff file, this information could have easily gotten out and you would probably not have known it. The easiest way in this case to remove the secret information is to just edit the file, and remove the diff lines for the file db.conf . The resulting file should look like the original patch file.
How To Use The New Patchfile
If you want to test your patch file to make sure that it works, you need to create a new test directory, since you don’t want to remove your original files:
cp -Rp project-orig project-test
To use this patch file, you must be inside the test folder in order to run it.
cp change1.patch project-test/ cd project-test patch -p1 < ./change1.patch
You should see something similar to:
Hmm... Looks like a unified diff to me... The text leading up to this was: -------------------------- |diff -Naur project-orig/test_file.conf project/test_file.conf |--- project-orig/test_file.conf Sat Apr 9 19:41:12 2005 |+++ project/test_file.conf Sat Apr 9 19:53:14 2005 -------------------------- Patching file test_file.conf using Plan A... Hunk #1 succeeded at 1. done
Why You Need -p1 With Patch
If you remember in the diff file, the files that are specified are not relative to the location that you are currently in. For example, you are trying to patch the file named ./test_file.conf yet the diff refers to the file project/test_file.conf . The -p flag tells patch to strip off a number of slashes from the beginning of the file. -p and -p0 have no effect on the path, but -p1 will change project/test_file.conf to test_file.conf . You should only need -p1 if you are using the commands that I have showed you here, but you may find a use for it in the future.
Conclusion
For a review, the creation steps are:
diff -Naur project-orig project > change1.patch
Then assuming you’ve checked it, and you are sending it to someone who already has a project folder of their own, the commands they must run are:
cp change1.patch project/ cd project patch -p1 < ./change1.patch
From my experience, when you are working with an Open Source Software project that you are modifying with your own little changes, patch files work very well to communicate your changes. Although not as efficient as CVS, it allows you to share your change with others using the same software. I have also noticed that it’s often the format that patches are released for software fixes in OSS projects.
No Comments | Tags: Programming Tools