Location: stefie10's Home Page / Technical / Forking 3rd Party Projects

One of the beauties of free software is the ability to tinker with it to make it do what you want. However after tweaking a piece of software to suit your needs, unless you get your patch accepted into the project’s mainline, it’s hard to keep it synchronized with future updates to the software. After thrashing around for a while, I solved this problem by using Quilt to maintain a set of patches and Subversion to maintain version control of the quilt patch set. (You could use another primary version control system besides Subversion; the key idea is to use quilt to maintain your patch set.)

This method has the advantage that you can fork without talking to the project’s maintainers at all. You don’t need to involve their version control system in your branches or anything. This is nice when you want to do a one-off project or make strange changes that they would never accept into the mainline. The main disadvantage is that it’s not possible to do the equivalent of “svn diff” to see what files you have changed. To use quilt, you must first explicitly add each file you are changing to the patch.

First, I set up my own Subversion repository to maintain the code. Then I check out the project’s code, using whatever version control system they’re using. If they’re using Subversion, I set up an svn:externals definition. (You can pass “-r” but not a date, so if you want to select the version by date you have to find the right revision number first. eg. project -r<revno> <project url>.) If it’s CVS or some other version control system, I write a Makefile to check it out. It’s important to keep track of the exact version of the project so the patches apply cleanly, so I make sure to specify a revision, branch, or date when I check out the project. Subversion updates the externals every time you “svn up” so it’s especially important to pick a revision there – if you don’t, quilt will get confused.

Then in order to keep my changes under version control, I use Quilt. Quilt maintains a set of changes as patches, and applies the patches to the base source tree. To use quilt, go to the directory above the project’s checkout. This directory should be in version control. Make a new directory “patches” and add it to version control. Make and add an empty file called patches/series. Then run the following command:

quilt setup -d  patches/series

This makes a “.pc” unversioned directory where quilt maintains what patches are currently applied. Now cd into the project directory. Run

quilt new 
to make a new patch. Run
quilt add 
to add files to the patch. Then edit the file that you added. Run “quilt refresh” to update the patch.

When you go up to the subversioned directory, the “patches” directory should contain a file containing the patch. This is updated when you “quilt refresh” based on the names of the files in the patch. The “series” file contains the name of all the files in the patch. I use quilt to update these files, and keep them all under subversion – my fork of the project is represented as a list of quilt patches.

To update the project, run “quilt pop” to remove all your patches. When I do this I usually run “svn status” or equivalent in order to make sure there are no changes that accidentally didn’t become part of a patch. Ideally “svn status” should show no modified files. If it does, it means you forgot to “quilt add” the file to a patch before you modified it. This problem is the main disadvantage of quilt: as far as I know, it’s not possible to run the equivalent of “svn diff” to see what files you have changed and want to add to the patch; you have to “quilt add” the files before you change them. This is because quilt doesn’t know about the whole source tree, but only about the files you have explicitly patched.

To synchronize with the mainline, run quilt pop -a to remove all your patches. Then run “svn up” or whatever you need to do to get a new version of the project in place. Finally, “quilt push -a” reapplies all the patches and rebuild the project. Sometimes you have to fix conflicts if this fails to work correctly. quilt stops at the first patch that fails, giving you an opportunity to fix the problem, refresh the patch, and then keep applying the rest of the patch streem. It’s good to do this periodically whether or not you change the underlying source to make sure there are no changes that you forgot to add to the patch.

The files in the patches directory are just patch files, that can be applied with the “patch” program, so they can be emailed as-is to development mailing lists, or wherever they need to go to get into the mainline.