May 15th 2014

While not directly related to continuous delivery, the strategy you use for branching will affect how you implement your deployment pipeline, and can shorten or lengthen your feedback loop.

Let’s make it clear from the beginning, one can’t safely do continuous delivery with long-running branches of code. Meanwhile, we may gain some benefits from cleverly using short-lived branches. The point of this article is to present some branching strategies with their advantages and drawbacks.

Preliminary note: while there is no reason the following couldn’t work with all SCMs, it will clearly benefit from using git or another tool where branches are first citizens.

Mainline Only

“Mainline” (a.k.a “trunk”, “master” or “baseline”) is the branch of your repository that contains the latest stable state of your development, and on which all other branches converge. The idea here is to commit only on mainline, which means you won’t have any other branches, except maybe for proofs of concept.

In this set-up, features are usually built in a bottom-up approach (user interface last), so that they only become visible when they are ready, with the latest commit that is part of their implementation. Alternatively, feature toggles may be used to activate features when the time has come.

What about maintenance branches? When you walk on the path of Continuous Delivery, you deliver, well, continuously… Therefore you won’t have any maintenance branch anymore but you will rather implement and deploy fixes as part of you regular development.

Pros:

Cons:

Advice:

A Branch per Feature

In this set-up, every feature is developed in its own branch. It is important at this point to define what a “feature” means in this context: it should be the smallest possible development that add a functionality to the system, in order for branches to be integrated into mainline as frequently as possible. Therefore a feature as seen by your client might be implemented as a set of many sub-features as just defined (small sets of related tasks).

Pros:

Cons:

Advice:

Variant 1: Branch Integration on Merge

This variant consists in creating a build pipeline for each feature branch, that will be triggered as soon as code is pushed on the branch. Being kind of annoying to do manually, the idea is to automate the pipeline creation when a branch is detected. The same can be done for branch/pipeline deletion as well. A future article of these series will present a way to exactly do that using GitLab and GoCD, but it could be done with for instance regular git hooks and some Jenkins magic.

Pros:

Cons:

Variant 2: Continuous Branch Integration

This variant goes one step further by merging all feature branches in another temporary branch, for each push detected on any of those branches. Tests will then be executed on that temporary branch (and only that branch). I did not try it yet, since I’ve first heard about it two weeks ago, at Mix-IT when the guys behind LesFurets.com presented their own way to continuously deliver.

The idea here is to:

With this technique, should a conflict be detected:

Note: as far as I know, those guys first merge all branches at once, and should a conflict occur, they retry it one branch after the other, to detect which branches are responsible for the conflict.

Here are the advantages and drawbacks, a priori (once again, I did not test it yet):

Pros:

Cons:

Conclusion

There is no definite answer to question of the best branching strategies, as it will mostly depend on your team and on your constraints. But it is important to know that there exist several such strategies, and that each one comes with its tradeoffs.

While this article is not exhaustive and only presents my views on branching, I sincerely hope it will bring ideas to some people, me included. So please comment!