Feature branches versus continuous integration
Posted at 07:00 on 13 July 2011
I love asking questions that get people to question their practices and assumptions. Especially when I get the impression that a lot of these practices have been adopted unthinkingly by a lot of people. That is why, in the conversation on Twitter surrounding my critique of Martin Fowler's position on feature branches, I posed the following two questions:
- If DVCS had come first, would Continuous Integration ever have been invented?
- What exactly do people understand Continuous Integration to be anyway?
In answer to the second question, you could of course point me to Martin Fowler's excellent essay on the subject, but I just want to make sure that you've read and understood it yourself. For it contains one point that most people seem to overlook when discussing CI, and it is this:
Everyone integrates their work into the main line every day.
For Subversion, this would be trunk. For Git or Mercurial, it would be a single master repository that does not permit multiple heads.
Clearly, most teams do not do this. While there are many tasks that you can break down into functional tasks of less than a day, there are many more that you can't. Consequently, if you wish to adopt this approach, you will be checking incomplete work potentially into production, hence the need for feature toggles.
It was this, specifically, that I described as a workaround for poor branching and merging support.
Here's a little thought experiment. Martin Fowler wrote that article in 2006, at a time when few people had even heard of distributed source control. Just suppose that Git had come to prominence ten years earlier and that the DVCS workflows with frequent branching and merging were standard practice industry-wide. Would he have mandated pushing your changes to the mainline on a daily basis then?
Somehow, I don't think so, and even if he had, it would have gained little or no attention. It would be widely regarded as a solution looking for a problem.
For what it's worth, long lived branches are a bit of a straw man here. If you are following an agile methodology such as Scrum, your features will naturally be fairly limited in scope anyway so you shouldn't ever reach that point. Nor am I convinced by the assertion that your mainline should act as a point of communication. That's what your daily stand-up meetings, sprint retrospectives and face to face communication throughout the day are for.
Of course, there are some situations where a daily integration approach will be beneficial, or even necessary. If you are stuck with an old-school centralised source control system such as Subversion or TFS, for instance, you don't have much choice. While it is possible in principle to adopt a branch per feature approach with these tools, in practice they enforce so much ceremony and risk around creating, merging, and switching between branches that it simply isn't practical.
Another scenario is where your team is new to branching and merging. Some novice DVCS users start off with a lot of magical thinking and unrealistic expectations about branching, dive straight in at the deep end with long lived branches and indiscriminate refactoring, then wonder why things go pear shaped when they attempt to merge. My general recommendation is to start with a CI-style approach and gradually expand into small and then larger feature branches as your experience and maturity as a team grows.
Third, some tasks are better suited to feature branches than others. Generally, the more dependencies your code has, the more frequently you will need to integrate. Changes to your data layer or shared classes will need to be integrated pretty much as soon as they're done, especially if you aren't following the Open/Closed Principle, whereas on the other hand, changes that largely incorporate new functionality, or that only affect your UI layer, will work fine even on long lived feature branches. Knowing where the limitations and possibilities lie and how to mitigate them allows you to adopt a much more flexible approach to feature branches. But it is certainly possible to adapt your approach to the maturity and expertise of the team, and the needs of your project.
Finally, it is worth noting that feature branches are only incompatible with this one specific aspect of Continuous Integration. Other aspects of CI, and of course pretty much everything about Continuous Delivery, are completely orthogonal concerns, and there is absolutely no reason why you should not do both.