Is the best branching strategy no branches at all?

Erik Gebers
7 min readMay 23, 2014

--

Not such a long time ago, I was discussing branching strategies with R&D team leads and our QA manager. We were working with feature branches, as they looked like the best solution to keep everything under control.

Developers wanted naturally to get a maximum of feedback on their work as soon as possible, in order to avoid the costly effort of plunging themselves in many weeks old code. QA wanted to optimize testing effort, therefore aiming at functional tests in an integrated branch. We ended up with a strategy which goal was to reduce the distance between the main product branch and the different feature branches, thus involving intermediate merges from the main branch into the feature branches. But it did not occur to me then that the best distance optimization between these branches was… no distance at all!

No branches and a blue sky, that’s something worth striving for!

Well I have to thank Jez Humble and David Farley for the tip. Even though I was already familiar with some chapters of their Continuous Delivery book, I stumbled upon their discussion on branching during my current reading of their work. They provide many arguments favoring a single development branch, the main one being that you cannot fully achieve continuous integration with many feature branches evolving at the same time. I would recommend to anyone working in the software industry to read the full book and hence benefit of all of their advices on branching and get their full motivation to work on a single branch. Here I will focus solely on why their recommendation stroke me as the right approach.

Let’s say you are working for a software company, developing a SaaS platform. You are already living by the agile manifesto, your teams are doing SCRUM and your ultimate goal is to deliver value to your customers as often as possible and without interruption of service (no maintenance downtime).

In such a context, your team may opt for branches, as a way of working together without obliging others to get to use your half-baked code. It is a very attractive concept that seems compatible at some degree with continuous integration: as soon as your feature is done, you merge it into the main branch, so everyone benefit from it without all the trouble they would have got with the « in progress » code. Moreover, branches let you choose what to integrate into a release, so if you discover a huge bug in a branch, you can postpone its delivery. Hey, that’s a lifesaver!

Wait, why am I bothering you with a « no branch » approach then? Well, first of all, as soon as you will start working with branches, you will hear people complaining about costly merges. These may be very subjective feedbacks, but you will have to start worrying nonetheless about the distance between your feature branch and the main one, because the bigger the distance, the more you will probably bleed doing the merge. And to be fair there are two dimensions of distance to consider:

  • time: the longer you wait to merge, the longer the code is « old » and you may be surprised as how fast a developer consider something old. It implies that the developer will have to switch contextes to do the merge (stop doing what he/she was doing, merge, and move back to their task). Focus is lost and when working with complex systems focus is everything. And while we are considering the time dimension, let’s not forget that developers take vacations, have accidents, etc. Delaying a merge implies you have to manage that variable as well.
  • code divergence: hard merges are the ones where there are many code changes in the same parts of your code base both in your feature branch and the main branch. Surely, the more you wait, the more you may be exposed to this kind of distance, but it depends also on what everyone in the team is doing. Because you will need to consider the distance between the different feature branches as well! Good team communication and intermediate merges into the feature branches may help here, but that does not look like scalable solutions and I would rather avoid having to deal with them at all.

As the lifesaver strategy is just delaying the merge, increasing the distance on both dimensions, the cost of the merge may surprise you. Still, you may choose to live with that, but you cannot ignore it. After some time though, your project being successful you will have to consider scalability of the teams and of the processes. Growing up brings stress, and that will certainly give you some exceptionally costly and troublesome merges with your branching strategy. Yet they are exceptions, so nothing to worry about (and battle scars make us proud). But a larger team working with branches means that the distance between branches grows faster. You may avoid that, working on the modularity of your application and creating specialized teams, supposing you can achieve that while handling the growth.

By the end of the day you may be successful with your branching strategy, yet someone (probably after looking at all your battle scars) will start speaking of creating an integration team to take the pain away and avoid all the faulty merges that ravaged the clients’ experience and stole you many sleeping hours. As we supposed you lived by the agile manifesto, this proposition should stir something in your guts: it is favoring process over communication and it is a solution to the symptoms, not a solution to the distance problem. It just adds more intermediary people between the problem detection and the problem solver. And more process, more time… which means even more distance!

At this stage, you may not be convinced, after all I did not write about the single branch approach yet! Well I left my main motivation for the end, so indulge with me a little longer.

Now having all developers working on the same branch of a product means that as soon as someone delivers some code change, they will be impacting the whole team. If the change breaks the product, people will complain about being unable to pursue their own work because of somebody else changes. You have probably already experienced it, it may even be your sole motivation for branches. After all they are a better solution than holding back all changes locally until the story is finished and we think that we can deliver the code without breaking the product.

But branches are the « easy » solution, and as aforementioned they come with their pros and cons. The tougher solution with a single branch is to learn to break down a story, a refactoring, a large bug fix in a set of smaller steps, that can be implemented without breaking the product. This should remind you of something… It is just the same you have already been doing with your releases if you are an agile adopter. Same thing just applied to a smaller scale.

I consider this solution tougher because you have to learn how to do it, as well as everybody else in the team. Branches seem naturally more attractive at first if you think about scalable processes: nobody have to learn anything in particular except the process, so it is easy to get it up and running and to onboard new team members. However, if we recall our context, we want to be able to deploy new code frequently, without downtime, without breaking things. If it were a simple task, there would not be so many discussions on the matter. It is hard and you need to get better at it. So being able to train your team on a daily basis looks like a very good option to me.

Delivering a story progressively will change the way your team works. Some may think it is impossible at first, but there are always means to do it (e.g. feature toggles and branch by abstraction). One awesome thing about it is that you will always need to think about your strategy before you start coding (even if your team always do it right, the isolation brought by branches make it easy to slip once in a while). Another benefit is that you will not have an unpredictable integration period at delivery time. If there are integration problems between features, you will discover them soon.

Finally, and that is what I really like about this approach, after getting everybody up to speed on working on a single branch you and your team will have acquired the right mindset. And that can make a huge difference. For the developers, you will not be working in a too procedural context, with recurrent integration crisis. And you will know how to move things forward in a really incremental fashion. For the business, I bet a team with the right mindset will let you advance faster and really manage critical situations instead of suffering them.

So, is the best branching strategy no branches at all? I am convinced it is, I will definitely be working with a single branch in my next projects! What about you?

Just a last thing if you are on a project already working with branches: Changing from branches to no branches should not be done too quickly. As Jez Humble and David Farley repeatedly wrote, Continuous Integration requires discipline in the team and working on the same branch could be a nightmare if the team does not play by the rules. I would strongly recommend reading chapter 14 of their book, where they expose different patterns for working with branches. If your cycle time is longer than a week, you will probably need to keep at least release branches. Another good read on the topic is Martin Fowler post.

--

--