Wednesday, December 7, 2011

Cherrypicking Made Easy

Branching strategy discussions are bike sheds. Distributed version control systems have brought some relief, as by their very nature they will force you to branch and merge more often.

Traditionally, most shops end up adding one change on top of the previous change, like so:


Invariably, they will end up stuck against a deadline, and find out that Feature A above cannot be fixed in time, so it needs to be pulled out instead. Unfortunately, Feature B relies on  code changes made to implement Feature A, and a nasty merge destabilizes the whole branch...

Instead, I advocate using a Production Branch, which only contains revisions of the code as it was when a release was made. These provide a stable baseline from which new work can be started. Every change starts life by being based on a baseline revision of the code:

As the release deadline approaches, you assemble a Release Candidate Branch. Note how natural and trivial this is when you use a distributed version control system: simply clone the production repo, then pull in the desired feature repos and merge:
 
Now, if a problem occurs, for example if Feature B causes trouble and you don't think it can be fixed in time, you simply discard your release candidate branch and create a new one, this time only merging in the features and fixes that worked:

If QA passes, you can release, and you copy your Release Candidate Branch into the Production Branch. The failed Feature B branch can then merge from the production branch (aka "rebase"), and maybe get on the next release:

Now choosing between continuous integration and parallel development isn't an either/or choice. Usually you will do both. Technically, you can consider the Continuous Integration model as an edge case of the Production Branch model, where you always just extrude one single branch after a release.

The point is to be aware of the risks and benefits of the choices you make:
  • Continuous integration reduces merge complexity, but commits you to either completing or manually backing out changes. Another advantage is that fixes propagate to all developers faster, but then again, not all developers appreciate having their world change in the middle of their work, so they might postpone updating their workspaces, thereby nullifying the advantage of simple merges.
  • Parallel development increases the tracking burden and might force you into doing a lot merging. In really bad cases, many of the merges will be repetitive as you recreate new release candidates using different combinations of features. The big win is that you do not need to commit to completing any particular feature or change at a specific time. You can make riskier changes and decide close to release time which changes to actually release.
The nature of distributed revision control systems will push you towards parallel development. That's a good thing, don't fight it.

No comments:

Post a Comment