Many contributions to Eclipse projects start as a patch. Patches are great because they can encompass changes to multiple files and make it easy to collaborate with others. Anyone can make a patch, so contributors don't need commit privileges to participate. Patches can be attached to tickets in the Eclipse Bugzilla so that committers can be confident of their IP cleanliness. The problem with patches is that they're static. That is, they don't evolve as the source code in CVS changes. Thus patches become stale, often resulting in committers asking contributors to re-cut a patch. So how do we overcome this problem?

I've had the pleasure of working from both sides of the problem. Starting as a contributor with the Textile-J contribution to Mylyn WikiText I created and maintained multiple patches, some small and some large. Eventually after earning Mylyn commit privileges I saw patches coming from contributors. The problem of the stale patch comes up again and again. Often contributions must wait a few days, weeks or even months before they're evaluated. During this time the files affected by the patch often change in CVS, thus rendering the patch unusable until it is massaged to fit the new code. Unfortunately this process of massaging is usually manual since the line-based merge algorithms used by CVS cannot account for non-trivial changes to source files.

So how do we evaluate and apply these valuable contributions? It's tempting to apply a stale patch and store conflicting changes in a temporary .rej file, and then merge those conflicting changes by hand afterwards. Though in some cases this approach makes sense, there is an easier way for those other cases.

The following formula can ease the pain for committers and contributors alike as they try to use a patch that has become stale:
  1. Start by attempting to apply the patch using the Eclipse 'Apply patch' functionality, either from the Team menu or from within the Mylyn task editor.
  2. Take note of which files have problems in the apply patch wizard.
  3. Exit the wizard without applying the patch.
  4. Take note of the time-stamp on the patch.
  5. For each file in the patch that was problematic, use the CVS 'Team->Replace With->History...' wizard and select the most recent revision that predates the patch. Take note of which revision was used.
  6. Now apply the patch. It should merge without issues. If not, you've missed something so go back to step 1.
  7. For each file that was moved back in time in step 5, use the CVS History to compare the revision that was used with the patch to the latest revision in CVS. Apply the changes that are shown in the compare editor to the file in the workspace.
The formula turns the problem around. Instead of trying to apply the patch to the latest revision, we apply the changes made since the patch to the patched files. Sometimes this can be much easier.

How do you choose which approach to start with? I recommend starting with an up-to-date workspace and try applying the patch. If proceeding down that path is starting to feel too hard, then revert your changes and try the formula described here. In some cases, the hard problem becomes easy! If not.... well, patches aren't perfect. Sometimes hard is just hard.