How to Make a Patch using Diff

I have had a lot of questions lately about making patches. On Backtrack we get a lot of user submissions and many times we need a patch rather than a modified source file. The reason being is that a patch can be documented and contains the specific changes made to the source file and can also be easily reverted. Patching is also crucial if you fix a bug in a program and would like to submit the fix to the author. In any case being able to create a patch is very  useful if you are working with Linux or any sort of programing stuff.

I decided to make a short post on how to make a patch and apply it:

So here is the scenario. You download a piece of code and it doesn’t work on your computer. You spend all day tweaking the script and making it work so that when it finally does work you totally forgot what you did. While you may have made good comments, thats not always good enough. So this is where diff and patch come in. In my example I am using a .py file that a friend of mine submitted to me to fix a issue in a python script by Edge Security called The Harvester.  Since the program is still active it would be uncool just to replace the original script in our .deb package so instead I made a patch.

So here is the scenario:


  1. root@bt:~# ls -laprt | grep .py
  2. -rwx------  1 root root   6553 Jul 13 12:19
  3. -rwx------  1 root root   5722 Jul 13 14:45

So I have to files one of which is the original and one is the one which was submitted to me modified and is working they way we want.

Just to illustrate the point here is a diff of the two files:


  1. root@bt:~# diff
  2. 91c91
  3. <
  4. ---
  5. >               #print data
  6. 95a96
  7. >               host = [] #this is needed.  We need to return 3 items, else python quits out.
  8. 97,98c98,100
  9. <                               y = string.replace(x, ' | LinkedIn</a>', '')
  10. <                               y = string.replace(x, '- Directory', '')
  11. ---
  12. >                               y = string.replace(x, 'LinkedIn', '') #was replacing ' | LinkedIn</a> but it was not weeding out the entries that were simply 'LinkedIn</a'
  13. >                               y = string.replace(y, '</a', '') #added
  14. >                               y = string.replace(y, '- Directory', '') #this was 'y = string.replace(x, '- Directory', '') which I think was a typo, as y would now be equal to original x without the changes made concerning 'LinkedIn' and '</a' entries.
  15. 101,102c103,109
  16. <                               resul.append(y)
  17. <               return resul,nexty
  18. ---
  19. >                               y.strip(' \n\t\r')
  20. >                               if len(y) == 1: #this block weeds out strings of length 1 that are only a whitespace
  21. >                                       if ord(y) == 32:
  22. >                                               continue
  23. >                               if len(y) != 0: #checks for zero length strings, which probably wont happen
  24. >                                       resul.append(y)
  25. >               return resul,nexty,host #as stated above, only returning resul,nexty makes python quit.
  26. 161c168
  27. <               res,nexty,host = run(word, cant, engine)
  28. ---
  29. >               res,nexty,host = run(word, cant, engine) #I placed a print after this line and found python never got that far.  After having run return 3 items for linkedin, it now finishes
  30. 163,164c170,172
  31. <                       if result.count(x) == 0:
  32. <                                       result.append(x)
  33. ---
  34. >                       if result.count(x) == 0:
  35. >                               result.append(x)
  36. >                               print len(result)
  37. 166,167c174,175
  38. <                               if resulthost.count(x) == 0:
  39. <                                       resulthost.append(x)
  40. ---
  41. >                       if resulthost.count(x) == 0:
  42. >                               resulthost.append(x)
  43. root@bt:~#

Okay so there are obviously a few differences so lets make a patch:


  1. root@bt:~# diff -u > harvester.patch

Thats it! No we have a patch which we can submit to the maintainers of which ever project we just fixed.

Now lets apply the patch and check our work:


  1. root@bt:~# patch < harvester.patch
  2. patching file

And then lets do another diff to see if it worked:


  1. root@bt:~# diff
  2. root@bt:~#

w00t! No output means our two files are exactly the same and the patch has worked properly

So that works but now you are maybe asking “what if I modified a bunch of files in a directory in order to get the program to work?”. It works pretty much the same way with a few extras.

First thing to do is make a copy of the entire directory:


  1. root@bt:~# cp -R tool_X/  Edited_tool_X
  2. root@bt:~#

Once you do that then you make all your changes to the new edited directory and then apply the diff command like this:


  1. root@bt:~# diff -rupN tool_X/  Edited_tool_X > toolX.patch
  2. root@bt:~#

Applying patches to entire directories is similar, but you have to set a p level. The p level instructs patch to ignore parts of the path name so that it can identify the files correctly.

Normally a p setting of 1 is sufficient. Change into the top level directory and apply the patch:


  1. root@bt:~# mv toolX.patch tool_X/
  2. root@bt:~# cd tool_X/
  3. root@bt:~/tool_X# patch -p1 < toolX.patch
  4. root@bt:~/tool_X#

Count up one for each path separator (slash character) that you remove from the beginning of the path, until what’s left is a path that exists in your working directory. The count you reach is the p level.

If at anytime you need to remove a patch you can do so with the -R option:


  1. root@bt:~# patch -R < harvester.patch
  2. patching file

Thats it for a basic intro to patching files and directories!

Version Control with Git: Powerful tools and techniques for collaborative software development (Paperback)

List Price: $34.99
New From: $12.03 USD In Stock
Used from: $1.75 USD In Stock

Mercurial: The Definitive Guide (Paperback)

List Price: $39.99 USD
New From: $18.66 USD In Stock
Used from: $1.73 USD In Stock