Creating patches
Generating patches, files containing the difference between files, is the domain of diff programs. There are many programs with this functionality; some stand-alone (diff), some integrated in IDE's (Eclipse, XCode) or version control systems (CVS). Diff can be found on most *nix systems. It is available in the free XCode Developers Tools on Mac and is included in the packages UnxUtils and Cygwin for use on Windows.
This page only deals with some basic principles using the command line utility diff (and the related cvs diff command). There is also a short video available, Rolling Patches in Drupal. Guidelines for patch submission to the issue tracker can be found in the Submitting Patches section.
CVS diff vs. diff
Diff compares two files. The cvs diff command will compare your locally edited file to the CVS repository version if you have a CVS checkout of the file being patched. The regular diff command will compare two local files (the original and and the edited version) to create a patch. The regular command can be used if you do not have an internet connection or do not have CVS set up on your computer (for more information on CVS see the CVS section of the handbook). Both commands are used with the same options and will result in usable patches.
Check your directory
The most important thing to ensure that a patch is usable is that you need to run the diff command from within the Drupal directory structure where you are patching. Ideally you should run diff from the Drupal root directory (the one that contains index.php, cron.php, etc). For example, if I have a copy of Drupal installed on my localhost in a folder called drupaltest (e.g. /www/htdocs/drupaltest) then I need to change into the drupaltest directory before I run the diff command. You can successfully run a diff from outside of the Drupal directory structure and create a patch file but the patch will fail to apply properly for other people since they won't have the same system directory structure that you do. Core patches should always be made from Drupal root.
One thing to keep in mind with patching contributed modules/themes vs. core patches is that not everyone puts contribs in the same location. So you should to do the diff from within the module's/theme's root directory rather than Drupal root.
Readability
Patch readability is very important for the review process and a patch not created with that in mind is likely to be rejected by reviewers. The two best options to accomplish this are the -u option for unified formatting and -p to show the function closest to the difference in the code, making it easy to see what function changed.
Separating your changes and whitespace
Separate each logical change into its own patch. For example, if your changes include both bug fixes and performance enhancements, separate those changes into two or more patches. Likewise all whitespace and code style cleanup should be in a separate patch and not mixed in with functional changes to the code. This just makes it harder for reviewers to see your substantive changes. Speaking of whitespace, keep in mind that if your text editor is set up to automatically remove whitespace, then you need to turn that setting off when editing code for a patch or you could create a messy patch without intending to.
Line endings and directory separators
Use Unix line endings (LF) and directory separators (/). Line endings can be converted manually with many text editors or by piping diff output through a dos2unix utility.
The command
So the basic command to use is:
cvs diff -up original.php > filename.patch
or
diff -up original.php new.php > filename.patch
Note that the symbol > will redirect the output to the file filename.patch. Give it a name that helps identify what the patch is for, e.g. modulename_code_cleanup.patch. If you do not include the > filename.patch part of the command the diff will go to the standard output for your system, which in most instances will be your monitor. This way you can see what the patch will look like before actually creating a file for it. Note that you can output the patch file to another place like your desktop or a folder you have created just for patches if you want by simply typing the path name in front of the patch name, e.g. path/to/desktop/modulename_code_cleanup.patch.
When you've modified multiple files in the source tree, use diff's ability to compare directories. Add the -R (uppercase) switch to cvs diff and the -r (lowercase) switch to plain diff to instruct the respective program to recurse (sub)directories. To compare files from the root directory, cd to the root directory and use a dot (full stop) in place of the directory name.
cvs diff -uRp directory > filename.patch
or
diff -urp original_directory new_directory > filename.patch
Adding/Deleting files
You use the -N switch to account for new or deleted files.
Adding
If you are using -N to account for a new file, you will also need to edit the CVS/Entries file for that directory and manually add a line for the new file. For example, if you have created a new file called newfile.inc in the modules/system directory, you will need to add a line at the end of the modules/system/CVS/Entries file like this:
Editing modules/system/CVS/Entries:
/admin.css/1.12/Tue Jan 16 23:15:28 2007//
/defaults.css/1.2/Fri Aug 25 09:01:12 2006//
/system.css/1.22/Wed Feb 7 03:46:21 2007//
/system.info/1.3/Tue Nov 21 20:55:35 2006//
/system.install/1.79/Fri Feb 16 16:39:46 2007//
/system.js/1.1/Thu Feb 22 16:33:29 2007//
/system.module/1.451/Thu Feb 22 16:33:29 2007//
/newfile.inc/0/New file//
If you are working from a tagged version the line will have the tag at the end. Use the other entries in the file to guide you:
/newfile.inc/0/New file//TDRUPAL-5
In this example, the "New file" string is arbitrary, but the 0 must be specified as the file's revision to show that it is new. Once this new line has been added cvs diff -Nup will properly include the new file in the diff.
Deleting files
If you are using -N to account for a deleted file, you will also need to edit the CVS/Entries file for that directory and manually change the line for the removed file file. For example, if you want to remove system.module in the modules/system directory, you will need to modify the corresponding of the modules/system/CVS/Entries file like this:
/admin.css/1.12/Tue Jan 16 23:15:28 2007//
/defaults.css/1.2/Fri Aug 25 09:01:12 2006//
/system.css/1.22/Wed Feb 7 03:46:21 2007//
/system.info/1.3/Tue Nov 21 20:55:35 2006//
/system.install/1.79/Fri Feb 16 16:39:46 2007//
/system.js/1.1/Thu Feb 22 16:33:29 2007//
/system.module/-1.451/Thu Feb 22 16:33:29 2007//
That's it! all you need to do is add a - to the version, so 1.451 becomes -1.451. This works for files only, not directories.
Here is the command:
cvs diff -upN directory > filename.patch
or
diff -upN original_directory new_directory > filename.patch
An example using cvs diff
- Make sure you have the latest CVS version of the file(s) before you begin making your changes: change (
cd) to the Drupal root directory and run the update command:cvs update -dP. - Make your changes to the file(s).
- When you are ready to roll your patch, change back to the Drupal root directory.
- Do a
cvs diff -up path/to/file/example.module > mypatchname.patch. This creates a new patch file in the Drupal root that you can now upload to an issue.
An example using diff
- Make sure you have the latest, clean copy of the file(s), either by downloading the latest tarball or updating from CVS (if possible)
- Create a working copy of the file you are editing in the same directory as the original (e.g. example.module copied to exampleNew.module).
- Do your edits to the working (new) copy.
- When you are ready to roll your patch, go to the command line and change (
cd) to the Drupal root directory. - Do a
diff -up path/to/file/example.module path/to/file/exampleNew.module > mypatchname.patch. This creates a new patch file in the Drupal root that you can now upload to an issue.

More discussion on line endings and directory separators
Thanks to some gentle coaching from Khalid Baheyeldin, an experienced drupal contributor, I came to discover an additional "diff" parameter called "--strip-trailing-cr" that could be useful to anyone creating patches on Linux (or any Unix) servers. Below I discuss when it is important to consider using this parameter and a typical use case.
Windows text files include a carriage-return ASCII character [CR, "\r", Hex 0D, or decimal 13, for example] that is not present in Unix text files. This difference in text file formats can defeat the purpose of using the "diff" command.
In my case, I created a new version of an existing module with just a few lines of code changed on my Windows PC using dreamweaver for PHP coding. I uploaded the new module to my Unix drupal site. The patch I then created wasn't the difference of the two modules but instead it was a union of both files. By union, I mean the patch included every line from the original module - not just the PHP lines I changed or added. The bloated patch was created, of course, because every line of text coming from my Windows file ended with an additional "\r" carriage-return ASCII character - not present in the original Unix version of the file.
Here are the steps I used to create a patch that solved the Windows to Unix mixed environment for me:
diff -up --strip-trailing-cr modules/amodule/amodule.module modules/amodule/amoduleNew.module > myNewamodule.patchAn alternative, as presented above in the main text, would have been to convert my Windows [aka Dos] module into Linux [aka Unix] format before creating the patch with these commands in a telnet window to my Linux server:
dos2unix modules/amodule/amoduleNew.modulediff -up modules/amodule/amodule.module modules/amodule/amoduleNew.module > myNewamodule.patch
Both methods above, produced exactly the same patch.
Best regards,
Ron Fredericks
Automatically adding files onto CVS/Entries
Adding multiple files manually into CVS/Entries files can be tedious and error prone.
Here's a small Unix shell script snippet (scrippet?) that can help you automate this task. This works for cases where no branch/tags are used. Add it yourself in the proper place if you like.
#!/bin/shADDED=`cvs -nq up|grep ^\? |awk '{print $2}'`
for file in $ADDED; do
echo '/'`basename $file`'/0/New file//' >> `dirname $file`/CVS/Entries
done
Adding new files to patches
As an alternative to manually adding new files to the CVS/Entries file, I can recommend the cvsutils script collection.
There's a perl script called cvsdo that allows you to do
cvsdo add foobar.phpto add a file locally (without accessing the remote repository). Then, you can create a patch with the -N switch (as described above) to include the newly added files. Very convenient.
See http://www.red-bean.com/cvsutils/ for details and download.
SVN cmd line with external diff
If you hold your drupal projects into SVN repositories, as I do, a handy way of creating a patch using the guidelines in this page and the diff external program would be:
# svn diff --diff-cmd diff -x -up modified.php > filename.patch