A GIT branching model for medium-size companies

This article explains how a medium size company, which has several teams, can adopt GIT for the source code management. As a software configuration management, GIT serves two different functions. The first one is the management support for controlling changes to software products, and the second one is merely development support for coordinating file changes among product developers. In particular here I want to talk about the branching model.

The following branching model is for a single product, whereas only the last product version is maintained (i.e. a web site or a mobile app). Additionally this branching model support an agile process model, where a new product version is released (hopefully) at the end of each team sprint.
This proposal is based on the “branch-by-purpose” model (@see The Importance of Branching Models in SCM), but it also provide a branch for the next release.

Main actors here are:

  • Developers, one or more developer teams
  • Release manager, or a release team
  • System administrator, or a sysadm team

This branching model is inspired by the work of Vincent Driessen.

Branches organization

A good branching model for medium-size technology department should absolutely have these characteristics:

  • Parallel Development
  • Collaboration
  • Release Staging
  • Support for emergency fixes (hotfix)

The proposed branching model has three branches, each with an infinite life. System administrators will always use the ‘master’ branch: everything is happy and deployable in master. Developers should always use the ‘develop’ branch, and all teams share this branch to commit their features. Also developers can’t commit anything in the master branch, the release manager is in charge of this operation. The release manager has its own branch ‘candidate’ in order to integrate in it the team’s patches, test these patches, promote versions, and then commit stable versions in the ‘master’ branch. The original work GitFlow does not have the ‘candidate’ branch, but uses a new branch for each release. I, instead, prefer to have the integration branch always with the same name: this can be useful in the future for the dependencies management.

Creating the three branches

Once created the repository with the master branch, you can create ‘candidate’ and ‘develop’ branches.

Now we have these branches:

Three Branches
Three Branches

The features

Any new feature should be developed in a separate branch. So, a developer that is on ‘develop’ branch…

…must start a feature branch, and share it with its team:

Rebasing keeps our code working, merging easy, and history clean. Developer should maintain this branch always rebased with remote branches ‘origin/devel’ and ‘origin/myteam/amazing_feature’, by doing these operations:

The branch ‘myteam/amazing_feature’ contains all the feature commits. These commit should not be done directly on the ‘develop’ branch because anything committed to this branch can be delivered on-line without any notice. Once the feature is done, the feature branch is reintegrated in the ‘develop’ branch.

Feature Branch
Feature Branch

At this point a “merge request” can be created also to manage the code review process. To finish a feature, perform these operations:

The option “–no-ff” preserves feature history and easy full-feature reverts merge. Now we can delete the feature branch:

Integration phase and release

At any time the release engineer can merge the new content of ‘devel’ and start an integration phase, as this picture show:

Candidate Branch
Candidate Branch

The integration starts with the code chill phase, that is the phase in which only small bugfixes are allowed. Personally I hate these bugfixes, and I prefer to perform all kind of tests directly on ‘devel’ branch: for me the integration phase should be only the final check. Once the code is ready to be deployed in production, we have the reintegration with ‘master’. At this point the release engineer can create the tag directly on master. Optionally the tag to be created can point before to the head of ‘candidate’ branch and then can be updated to point to ‘master’.

Deploying and emergency fixes

Everything is happy and up-to-date in master: the system administrator can use tags created by the release engineer to deploy a specific version of the product. This support the deploy of the latest version and also the roll-back to a previous version. Once reintegrated the branch ‘candidate’ into ‘master’, a new tag is created following these steps:

If for testing purpose you already created the tag 1.2.3 pointing the ‘candidate’ branch, now you can move this tag by using the option “-f”.

Also the emergency bug fixes (hotfix) are supported by this model, as shown in this picture:

Hotfix Branch
Hotfix Branch

Useful configuration

Autosetup rebase so that pulls operations rebase by default

DOs and DON’Ts

No DO or DON’T is sacred. You’ll obviously run into exceptions, and develop your own way of doing things. However, these are guidelines I’ve found useful.


  • do master must always be deployable.
  • do all changes are made through feature branches
  • do use a “merge request” (aka “pull request”) to manage code-reviews
  • do rebase to avoid/resolve conflicts before to merge
  • do keep master in working order
  • do rebase your feature branches often
  • do tag releases
  • do learn to rebase and merge


  • don’t fork
  • don’t merge broken code.
  • don’t commit onto master directly.
  • don’t hotfix onto master! use a specific hotfix branch.
  • don’t rebase master.
  • don’t merge with conflicts. Handle conflicts upon rebasing.

Leave a Reply

Your email address will not be published. Required fields are marked *