Skip to main content

Branch-per-feature, and it's another world

Posted by fabriziogiudici on August 9, 2009 at 12:41 PM PDT

After some experimenting and after moving all my projects to Mercurial repositories at Kenai, I've at last started regular working with it. Well, it's another world - I've already blogged a bit about some cool features of working with a Distributed SCM.

Today I'd like to talk about "branch-per-feature". It's a mode of working in which you create a branch of your repository for every feature (bug or RFE) you're working on (with the exception of very small and predictable fixes). In contrast with the most typical way in which people work with branches - i.e. for entirely new work, or for maintaining past releases - branch-per-feature implies branching at finer grain. If you're working on - say - seven issues at a time, this means you have seven branches active in addition to the default one. As soon as the work on a feature is completed (which for me means as soon as the related tests are successful) you merge the branch to the default one and then close it.

For instance, at the moment these are the branches in jrawio:

[Mistral:Projects/jrawio/src] fritz% hg branches --closed | sort
2.0                          540:0dd29bb11aec
default                      556:a9e02a1f070d (inactive)
fix-JRW-120                  562:a82b7ed21b94
fix-JRW-162-and-JRW-194      367:e75735d2055c
fix-JRW-187-1                408:1a0cbede4cb8 (closed)
fix-JRW-203-1                558:92fcd592cc51
fix-JRW-6                    560:eb9031bec74c
nef-fixes-1                  555:9ecb14834d0f (inactive)
src                          286:d9692def01a2 (closed)

Forget "src" which was created by the tool used for import the repository from Subversion; you can see the "default" branch, the "2.0" branch where I'm experimenting with brand new stuff, and all the others are branches related to specific issues (sometimes multiple issues are grouped together if I think - or preliminary investigation has suggested that - the solution is similar).

The biggest advantage of this approach is that you're virtually always read for making a release: in fact, by construction, the default branch is always in good shape (i.e. all or most tests are successful). For instance, I'm thinking of planning fixed-interval releases (e.g. every 2 or 3 weeks) every time putting into it the set of features that have been completed (eventually, I could skip a release if in the meantime no features came to completion). In this perspective, I've still to fix some issues with Hudson and my workflow, but at the end of the story I should be able to make a release with just the pressure of a button in Hudson.

This sounds really good especially with jrawio, whose work requires a lot of reverse-engineering investigation, often taking many days (or weeks) interleaved with other work. In the past, working always on the trunk was one of the main reasons for which I wasn't able to plan regular releases; with Mercurial and branch-per-feature I has been able to publish 1.5.{0, 1, 2} in one month.

Of course, this is not a free lunch. The idea works well if different features impact mostly on different part of the code, mostly different classes. But this is what OO design brings, right? And in fact this is what I'm experiencing with jrawio. As usual, long-lived branches will benefit from periodical synchronization with the default branch, so that they don't get too different at the point that merge raises conflicts. Another point is your capability to mentally track all the branches, and eventually sharing the information with other committers. But this is easy: with Jira, I just added a custom field "Progress in branch" where I document, for every issue, where the work is being done.

What I'm missing is a graphic tool to display branches and merges - Mercurial provides a simple web-based graph feature, but it's too cluttered to be useful. I'm seriously thinking of writing a specific plug-in for NetBeans, that could be easily made thanks to the Visual Library. I have still to figure out whether such a tool was really useful or only cool ;-)

Before finishing, I must say that you don't need to use Mercurial or Git for working in the branch-per-feature way; indeed any SCM supporting branching should do (for instance, this guy has just started a series of posts about branch-per-feature and he's using Subversion). It's that Mercurial handles branches in a much simpler (and faster) way, and for me it changed my way of working.

Related Topics >>

Comments

Hi, a few follow-up

Hi,
a few follow-up questions:

  1. How is your CI set up? Do you have a project only for the default branch, which then only builds when a feature branch is merged? Or do you create projects and test environments for every branch?
  2. What is your experience with conflicts in the branches? Isn't it your experience that you don't refactor as much in the branches as you would (maybe even subconsciously) to prevent merge conflicts?

Thanks,
Andreas

Hej, are you aware of the

Hej,
are you aware of the fine article Martin Fowler wrote about Feature Branches and some of the caveats? You can find it here: http://martinfowler.com/bliki/FeatureBranch.html

I agree that reasonably sized activities are worthy of their own configuration. I used cvs for 6 years and converted to svn many years ago. I still employ this pattern today. But the periodic synchronization of your project branch, with it's parent, is laborious... not bad with 4 developers, but painfully unscaleable with 40+... and as you mention, not having a graphical view is tough to gauge activity and progress (or divergence). I still use svn for small projects, and am interested in mercurial for an alternate DSCM. But for production projects, I'm very satisfied with accurev. It is commercial, but parent-child inheritance eliminates "periodic syncs" and provides a good java-based UI for viewing configurations and relationships. Child streams (not branches) dynamically inherit new changes from their parent...grandparent... etc. I found this the most unique difference between the traditional branch-based tools. I'll still use branch tools for smaller teams and the branch-per-feature is essential to create just-enough-stability. But required periodic merging and lack of visibility forced me to look beyond....

Soon I will join your Mercurial trip: https://kenai.com/hg/puj~arena and I will use our Hudson to continuously integrate its artifacts.. let's see... branch per feature seems a nice to have feature...