Comparing Git branching strategies
Tags: git, vcs, branching, devpractices
Published: 2020-09-16 09:29:24

# Introduction

With a very tiny footprint and lightning fast performance, [Git](https://git-scm.com) has become the de facto standard for source control management. Branching is an essential feature of a VCS ([version control](https://en.wikipedia.org/wiki/Version_control) system), that allows developers to diverge from the main line of development and continue their work on multiple features in parallel, without affecting the main line. Branching is often considered as Git's "killer feature" as its incredibly lightweight to perform branch operations, like [creating a branch or switching between branches](https://git-scm.com/docs/git-branch), which are often instantaneous.

Git doesn’t enforce any particular branching strategy and allows teams to tweak it, as it fits the team’s culture. As a result, teams and organizations are often required to choose a particular branching strategy that matches their release cadence, while optimizing productivity depending on their team size, strengths and weaknesses. 

This post performs a comparative analysis of the three most popular branching strategies, namely, *Git Flow*, *Trunk based development* and *GitHub Flow*.

# Branching Strategies

The popular branching strategies can be divided into two categories, mainline based and feature based.

![Branching categories](https://dev-to-uploads.s3.amazonaws.com/i/mnytf9fq0z5vywjv5ivc.png)

# Feature based

## Git Flow

Published in 2010 by [Vincent Driessen](https://nvie.com/posts/a-successful-git-branching-model/), Git Flow provides a robust workflow with a strict branching model, focusing around project releases. At its core, the repository holds two main branches, with an infinite lifetime:
- `main` (or master) – the official release history of the project
- `develop` (or development) – the integration branch for features

To aid development and release activities, a variety of supporting branches can be used, which are short lived, unlike the main and develop branches, and aim at providing support for production releases, hot fixes, and parallel feature development.
- `feature-x` (feature branch)
- `2020-rel-1` (release branch)
- `2020-rel-1-hotfix-1` (release hotfix branch)

![GitFlow](https://dev-to-uploads.s3.amazonaws.com/i/i6io1rbsgbm08vu2177a.png)
*Figure 1: Git Flow*

As seen in figure 1 above, Git Flow outlines the below workflow for managing development and release activities:

1. The `develop` branch is the primary hub for development and collaboration.
2. Each new feature resides in its own feature branch and is created from `develop` as its parent.
3. Once a feature is complete, the feature branch is merged to the develop branch and can be deleted.
4. A feature branch never interacts with the `main` branch.
5. When all the features required for a release are complete and merged in the develop branch, a release branch is forked off of develop.
6. Only bug fixes can be added to this release branch from now on.
7. Having a separate release branch enables teams to continue working on other features and merge them in develop for integration testing.
8. Once the release is complete, the release branch is merged to `main` and *tagged* with a version number. 
9. Additionally, the release branch is also merged back to `develop`, which may already be ahead with feature merges for the next release.
10. Hot-fix branch is used to quickly patch production release and are branched off of `main` branch. They are similar to release branches and once complete, they are merged back to `main` and *tagged* with an updated version number. 
11. The `hot-fix` is also merged back to `develop` branch, to ensure the fix isn’t missed in the subsequent releases.

# Mainline based

## Trunk Based Development (TBD)

TBD is a popular version control strategy in [centralized version control systems](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control) (VCS) and is equally applicable to distributed VCS, whereby developers commit their changes to a shared `trunk` (or `main`) branch in repository. The goal of TBD is continuous integration and thereby continuous deployment, which is achieved via a series of small and incremental commits directly into the `main` branch.

![Trunk based development](https://dev-to-uploads.s3.amazonaws.com/i/rtyv309m3vrf1qpbqll8.png)
*Figure 2: Trunk based development*

Trunk based development outlines the below flow for minimal branching and continuous delivery:

1. Feature work is broken down into small batches which are then committed to `trunk` by developers at regular intervals, sooner the better.
2. This ensures minimal integration overhead and allows Continuous Integration systems to run a suite of automation tests to keep the build process green (up and running).
3. To support features that span across releases, [*Feature toggles*](https://martinfowler.com/articles/feature-toggles.html) are used to conceal the point of entry of the feature.
4. Another way to conceal the feature in development is [*branch by abstraction*](https://martinfowler.com/bliki/BranchByAbstraction.html), which essentially introduces a temporary abstraction layer to encapsulate both new and old behavior during development.
5. Decoupling of release from launch via feature toggles or branch by abstraction provides the operational benefit of graceful degradation on failure, and the business benefit of [*dark launching*](https://martinfowler.com/bliki/DarkLaunching.html) features.

## GitHub Flow
Created by and extensively used at [GitHub](https://github.com), GitHub Flow is a lightweight, branch-based workflow that supports teams and projects focused primarily on continuous delivery. Unlike Git Flow, there are no "releases" to production, deployment happens frequently, almost every day, even multiple times a day. 

At its core, the repository holds two types of branches:
- `main` (or master) – the mainline branch
- `feature(s)` – the feature branches to support parallel development.

![GitHub Flow](https://dev-to-uploads.s3.amazonaws.com/i/qvj0wrhm4mptg2b15vjr.png)
*Figure 3: GitHub flow*

As seen in figure 3 above, the GitHub flow outlines the below workflow for managing development and release activities:

1. Feature branch is created from `main` for feature development.
2. Commits are added as required, locally. 
3. A _pull request_ is created to start a discussion on the commits to receive feedback on the changes.
4. Review comments are a critical part of the process.
5. Once the review is complete, tests and checks pass, and the pull request is approved by someone else, the branch can be deployed to production.
6. If the feature branch causes any issues in production, rollback can be performed by deploying the `main` branch.
7. If the changes work as expected in production, the feature branch is merged into main.
8. As this flow promotes continuous deployment, there is no difference between a hotfix and a small feature branch.

## How TBD differs from GitHub Flow
Both TBD and GitHub flow follow a trunk or mainline based branching strategy for development and release. However, they differ in one significant way.

GitHub flow proposes deployment to production **before merging** to `main`, whereas TBD proposes deployment **after merging** to `main`.

In an enterprise with large number of developers working on the same project, GitHub flow could lead to significant wait time as every approved pull request should be deployed to production, leading to a bottleneck. 

Hence, for such scenarios, TBD with a predefined release cadence, is preferred, where the deployment occurs after merge to main and the commits present in the main branch at the cutoff date are deployed to production.

# Comparative Analysis

|     Concern                      |     Git flow         |     GitHub flow                     |     Trunk based        |
|----------------------------------|----------------------|-------------------------------------|------------------------|
|     Branching overhead           |     significant      |     lightweight                     |     lightweight        |
|     Deployment branch            |     release          |     feature                         |     main               |
|     Deployment trigger           |     release cycle    |     approved pull request           |     merge to main      |
|     Most stable branch           |     main             |     main                            |     main               |
|     Hotfixes via                 |     hotfix branch    |     feature branch                  |     main               |
|     Delivery cadence             |     releases         |     continuous                      |     continuous         |
|     Merge effort (merge hell)    |     significant      |     minimal                         |     minimal            |
|     Feedback timeline            |     long and slow    |     quick                           |     quick              |
|     Production issues            |     rollback         |     quick fix via feature branch    |     feature toggles    |
|     Project Types                |     enterprises      |     open source, startups           |     enterprises        |

# Common Code Quality Practices

Regardless of the branching strategy your team chooses, here are few practices that we implemented to ensure high code quality.

✓ Static code analysis - new code smells `0` and new bugs `0`.
✓ Dynamic scan analysis - Mandatory `0` medium or high issues.
✓ Code coverage - subjective, at-least `80%` on new code.
✓ Mandatory work item association.
✓ Reviewed by at-least two _other_ developers.

#### Credits
The images are copyrights of respective authors, as applicable.