The best branching model to work with Git

Grazi Bonizi
6 min readMay 22, 2018

--

A lot of people ask me about Branching Models, which starts a nearly philosophical discussion: which is the best model with Git?

First of all, why Git?

Git is the de facto version control system. It is the most accepted by the technological community, and one interesting fact is that even Microsoft, that created the TFVC (Team Foundation Version Control), encourages to use Git:

Git is the default version control provider for new projects. You should use Git for version control in your projects unless you have a specific need for centralized version control features in TFVC. — Comparison Git vs TFVC

Before we talk about branching strategies using Git, it is important to understand the basics of Git version control. I see a lot of people that uses IDE’s and visual tools to do the basic operations like commit and push changes, create and merge branches, compare history and revert changes, without learning how Git actually works. It can be enough at some scenarios, but to be able to decide which branching model is best for your team, deep dive into the Git documentation. It has some nice tutorials, like the Git User Manual if you want to get started, and the Git Cheat Sheet, if you already know the basics and want a quick overview of the most common commands.

Assuming that you know the basics of Git and understand why to version control your code, let’s move to the next question:

What do I expect from a branch strategy?

It depends on the size of your team, the number of teams working on the project, if the project has more than one feature being developed at the same time, the frequency you release code to production… the more complex your scenario, more you rely on a proper branch strategy to support it.

We can summarize the main things we expect starting with a small scenario then growing it up.

As an individual (even in a demo ou personal project), I need

  • To have the history of my changes
  • To be able to compare my changes and revert them if necessary
  • In case I need I to create a bugfix, I can develop and deploy it without affecting the features I am currently working on

As a team, besides the requirements above, I need

  • To be able to work and to push changes to the server without affecting my coworkers
  • To merge my changes with my coworkers’s and to solve any conflicts in the simplest way possible
  • To ensure the quality/ basic standarts of the code regardless of the number of people involved

This is the base of code versioning. I dare to say that it’s the base of DevOps.

The simplest functional model

A model that would meet these requirements in a really simple way is:

Simple branch strategy for small teams or individuals

Is practice, what is happening is:

We have two long-living branches, master and develop. Each release to production comes out from master and has a tag with a named version. I wouldn’t tell a pair of programmers that they have to work on the develop branch since the beggining, first because it usually doesn’t happen, and second because the real need of a second branch starts after the first release to production (v1). This way the team can work on new features on a separate branch, while the master is intact untill the next release. The main advantage of this approach is: if you have bugs to fix, which you’ll always do, you’ll be able to provide the fix without having to stash your changes or speed up the features you are developing. So in these situations, we create a short lived branch for the fix, merge on the master and deploy to production with a new tag (v1.1), and propagate the fix to develop. When the new features are ready, they would already have the fixes, and merging with the master branch wouldn’t be a trouble (v2).

It can really work on individual or small teams, considering that they may have trouble merging their changes on develop, as there’s more than one person working on the same branch. But with a simple structure of Continuous Integration concepts, these kind of issues are minimized.

One disadvantage of this model is that is not really clear what is you’re working on. Let’s imagine that the develop branch has a group of commits related to a feature that you decided not to ship anymore, or not for a while. It will not be so easy to rollback the code, specially if you are working on other features at the same time. Also it won’t be any easier to get back the discarded changes if you need them later.

Stepping forward — using Feature Branches

As branches are really cheap in Git — they are really easy to create, merge or delete — we should create short-lived feature branches if we want to overcome that disadvantage, isolating the development and being able to discard or deploy it individually.

We can have more than one feature being developed at the same time. Maybe one feature can be delivered before the other, or a group of features should be shipped togheter to production. Whichever the case, the development of one should’nt affect the development of the other. Of course, it works better with agile planning — the features should be big enough to bring business value, but small enough to be delivered without having a lot of new releases of the code, so it wont be so outdated when you want to merge it.

Feature branches combined with integration branch

As the picture shows, v2 will have feature 1, and v3 will have feature 2 and feature 3. Maybe the merge of feature 3 with integration branch generates a few conflicts, that the team will have to work on to make v3 available.

In that strategy we have short-lived feature branches, that will be merged as soon as possible to the integration branch and then be deleted. The releases will still come out from the master branch. I prefered to name the second branch as “integration” instead of “develop” because usually the features wont be developed direcly on this branch — the purpose of the integration branch would be literaly to integrate the code of all teams before shipping it to production. Note that the bugfix still propagates the changes to all active branches.

This strategy is good enough if you are not Continuously Deploying code to production. If you want more control of what is being delivered, to have an integration branch may be a good idea.

For more complex scenarios there’s always GitFlow, which is more robust comparing to the previous alternatives. It has a well-known model that has an implemented git extension and some visual options (Source Tree, GitKraken).

I worked in a company that sucessfully used GitFlow model in it’s projects, but I have to assume that we actually didn’t need all of it. Some of the projects / teams were so small that the first approach I mentioned here would be enough.

Working closer to master

If you want to continuously deploy everything you code, maybe some other strategy would be better, like Trunk Based Development, which has a single long-lived branch, and features are merged direcly to it, or GitHub Flow, which has a really nice and interactive learn-to page, that helps not only how to understand the model, but also the process of pull requests and revieweing the code. The main difference of GitHub Flow is that code is deployed to production from the feature branch, so the changes are verified in production, and after validated they are merged into the master branch or discarded.

In Microsoft Build 2018, which happened on 07–09 May, Edward Thomson presented the Release Flow, a branching model the VSTS Team uses. It’s similar to Trunk Based Development and GitHub Flow considering it has only one long-lived branch, but they do not continuous deploy. Instead, they use Release Branches to deliver the product of their sprints, and cherry-pick the code when they need to provide an urgent bugfix. In case you missed it, you can wacth the talk on the video bellow:

Making a decision

There’s no perfect model that will work well in any kind of project or team(s). Better than choose an aproach that is commonly used by companies that are completely different than yours, is to understant the needs of your project and your team, understand how Git works and choose the simplest model that fits most of your needs.

--

--