Feature branches versus continuous integration
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.
Nice write up. There is a concern about qa being involved in a feature at a point in time when it’s too late.
To clarify, are you suggesting that with feature branching you would have a separate branch for EVERY feature/card or only those whose lifetime seem somewhat larger than normal? In other words, if your team played 10 cards in one iteration would you expect to have 10 feature branches or maybe 1 or 2?
Not necessarily. Some teams do indeed do it that way, but there’s no hard and fast rule. It all depends on the team, their experience, the requirements of the project, their source control tool, the nature of the features in question, and how much refactoring is going on and where.
In general my advice is for teams to start off with a CI-style approach (everyone integrates at least once a day), and to expand into first short lived and then longer feature branches once they understand how branching and merging works, what they can get away with, and what causes problems and how to mitigate them.
So ‘feature branching’ as I’ve encountered it in the wild has taken the form of ‘every card gets a branch and gets merged in when it’s done’. Sort of like ClearCase (shudder) except more branches. This would be akin to feature toggles where EVERY feature started with a toggle. This practice causes real problems for very little gain (continuous delivery aside…can’t speak to that) on normal functional teams where most features complete before deployment.
Correct me if I’m wrong, but what you’re describing is feature branching as a tool to be used when appropriate and not a standard part of your every day work flow. In that sense I would agree that it can certainly be a useful tool. I would not agree that it is a fundamentally better approach than feature toggles….their appropriate usage scenarios don’t seem to entirely overlap.
You’re quite correct there — it’s a tool to be used when appropriate. As I said, it all depends on the team, their experience, the nature of the tasks, and the needs of the project.
If your CI can’t handle long lived feature branches get a better CI. Having multiple builds for a project is not that complicated.
Great post I especially found it useful where you stated everyone integrates their work into the main line every day. Everyone usally does. I’ve done it and still doing it. Good article.