In this article we will dive into what a branching strategy is, why you should consider getting one if you don’t already have one and some of the most common branching strategies available.

What is a Branching Strategy?

When development teams work on a codebase, there is a need to keep work tasks separate, such as development on new features and bug fixes. A branching strategy is a set of rules and practices a development team follows when creating, managing, and merging branches in a version control system, such as Git.

The goal of a branching strategy is to facilitate parallel development, isolate changes, managing releases, and ensure code stability.

Why having a Branching Strategy is important

Having a clearly defined branching strategy helps in several areas. Firstly, it fosters collaboration. Branches facilitate code review processes. Developers can submit their changes through pull requests or merge requests, and reviewers can assess the modifications before they are merged into the main branch. Secondly, having a branching strategy enables stability. Features can be developed on in isolation and be merged into the main development branch when ready, so the main branch remains stable. This also allows for parallel development. By doing this, it is ensured that the codebase is always in a deployable state.

Finally, it enables historical tracking. Each branch represents a specific set of changes over time. This historical tracking is valuable in understanding when and why certain changes were introduced, helping with debugging and accountability.

Branching Strategies available

We have now covered what a branching strategy is, and why having a branching strategy is important. This then raises the question: Which branching strategies are available? In the coming subsections we will be looking at four different branching strategies: Git Flow, GitHub Flow, GitLab Flow, and lastly, Trunk-Based Development.

Git Flow

Git Flow, first introduced back in 2010 by Vincent Driessen in his blog post “A successful Git branching model”, features a set of different types of branches. Let’s walk through the terminology.

  • main — This is the branch that reflects what has been released to the customer.
  • develop — The develop branch always contains the latest delivered development changes for the next release.
  • hotfixes — If a critical bug appears in production, a hotfix branch can be created to quickly remedy the bug. Once a fix has been made, it is merged into the main branch, and into develop.
  • release branches — To prepare for a new release, a release branch is created on which only bug fixes are remedied. Once it is ready for release, it is merged into main.
  • feature branches (or topic branches) — whenever a new feature needs to be developed on for an upcoming or future release, a dedicated branch is created.

Git Flow

Git Flow has a dedicated branch term for each type of work, making it transparent how to branch. However, Git Flow also has the risk of creating excessive overhead work, since there are a lot of active branches in use simultaneously. In smaller development teams this can become tedious administrative work, for example when a commit on a hotfix branch has to flow all the way out to feature branches.

GitHub Flow

A simpler branching strategy compared to Git Flow, is the GitHub Flow. With this strategy the types of branches are reduced to two types:

  • main — Just like Git Flow, the main branch contains the source code that has been released to production
  • feature branches — Whenever a feature or bug fix is worked on, a dedicated feature branch is created.

GitHub Flow

GitHub Flow is an easy to use and fairly straightforward branching strategy to use. Every time development on a new feature or bug fix is started, a feature branch is created. When it is ready to be release, a pull request is created against the main branch, and it is subsequently merged in.

GitLab Flow

The GitLab Flow branching strategy resembles the GitHub Flow, with a few extra layers. Often organisations have a need for more than one environment where the code runs. GitLab Flow introduces environment branches. The purpose of the main branch also changes. So the available types becomes

  • main — This is now the initial environment the code is deployed to.
  • feature branches — Whenever a feature is worked on, a dedicated feature branch is created.
  • environment branches — A branch representing what code is currently deployed in the given environment

An example using this strategy is to use the main branch for a staging environment, a pre-production branch that is mapped to a pre-production environment, and a production branch mapped to the production environment. New changes are then merged over to the next environment branch and rolled out on the respective environment.

GitLab Flow

The GitLab Flow strategy makes it easier to decipher what is currently running on a specific environment, while simultaneously enforcing a correct way to promote the new features through the individual environments until it ends in production.

Trunk-Based Development

The Trunk-based Development (TBD) branching strategy takes a bit of a different approach from the previously mentioned strategies. This branching strategy only uses two types of branches:

  • main (also often called trunk) — which all developers work on simultaneously
  • release branches — Branches containing the specific releases. When a new release is created, the old one is retired

By only working on a single branch, you are enabling pure continuous integration. Every new commit is tested against the main codebase, making it possible to catch errors early. Developers only commit to the main branch, and do not commit to the release branches. If bug occurs in production, a fix is made on main and release through a new release version.

Trunk Based Development

TBD comes with a couple of caveats that you ought to look out for, such as the following:

Team size – TBD enables fast feedback for smaller team sizes, but can require short-lived feature branches depending on the team size and the rate of commits.

Build server — If there are more than a a few developers on the project, a build server is needed to verify that the commits have not broken the build after they land in the trunk.

Branch by abstraction and feature flags — Branching by abstraction where an interface is introduced can for some teams be a new experience. The abstraction layer is introduced in the software to enable the team to work on changes that takes an extended period. In the same category is feature flags where feature logic can be toggled active at command. This allows new code to be introduced to main without breaking the business logic.

Which should you choose?

Choosing the right branching strategy involves a set of considerations:

  • Project Size — For small projects aiming to minimize the administrative overhead, Trunk-Based Development strategy. However, for bigger projects, the GitLab Flow approach might be more suitable.
  • Team Structure — The structure of the development team is a crucial factor. Trunk-Based Development is streamlined for smaller teams, while GitLab Flow might be more beneficial when there are external teams that needs validate the release before it hits production.

In reality, there is no one-size-fits-all solution. The selection of a branching strategy should align with the unique requirements of the development team and the project’s nature and complexity. It’s a case-by-case decision that necessitates careful evaluation.

Moreover, it’s common for development teams to initiate with one strategy and refine it over time based on evolving needs. The key takeaway lies in adopting a strategy that fosters productivity by offering a clear and consistent framework for organizing work. Flexibility and adaptability are paramount, ensuring that the chosen strategy evolves in tandem with the team’s changing dynamics and project requirements.