BackHub Blog

Git Branching Strategies, Explained

Git was designed to help mitigate problems everyone hates having to solve. Yet even though it’s supposed to prevent you from tying yourself in knots with versioning, you can still easily do just that. 

To avoid chaos, you need a few rules to help define your workflow and make sure your team uses Git consistently and effectively. This article is about three common branching strategies and what they bring to the table. 

These strategies tell you exactly how to work with Git, with fixed systems for creating and merging branches. They aren’t the only strategies around, so if none of them seems right for you, remember there are others available.

You’ll learn about the following strategies:

  • Git flow uses a master and develop branch alongside smaller branches for features, hotfixes, and releases.
  • GitHub flow uses a main branch with feature branches used for development and merged back into the main via pull requests.
  • GitLab flow adds a production branch and other optional branches to allow you to check code at different stages of the development cycle.

They may sound confusingly similar, but they differ in significant ways. Understanding this is key to picking the right one. Get your branching strategy right, and Git is less of an accident waiting to happen.

Here are the details on each strategy, as well as their pros and cons.

Git Flow

With Git flow, you have two main branches, a master branch and a develop branch. Work is done on the develop branch and when it gets to a stable point, it is merged with the master and tagged with a release number.

developing and merging process in git flow

Alongside the main branches are supporting branches including feature, release, and hotfix. These branches have a finite lifespan and strict rules regarding their use. 

The feature branch branches from and merges to develop. It’s used for a specific feature and merged back when finished.

Release branches branch from develop** and are merged back into both develop and master. They are created when the develop branch is nearly ready for release and used to finalize everything and fix minor issues. When the code is ready for release, it is merged to master.

Hotfix branches are for problems or urgent bugs that need to be fixed in the release code. They branch from master and are merged back to master when finished, and also merged with the develop branch.

Git flow is the oldest strategy here, and by its author’s own admission, it may not be as relevant to modern practices as it once was.

It allows you to monitor all code closely and is well suited to projects where releases are spaced out. It is also popular with open-source teams who want to monitor incoming code.

For continuous integration and projects where you release often, Git flow’s slower nature is a problem. You can also have problems with merging, especially if new features spend a long time on their own branch and fall out of sync with the rest of the project.

However, Git flow is much better than no strategy at all, since it allows you to clearly define what goes where, along with how and when to merge branches. For many projects, though, consider a more modern strategy, such as the following two.

GitHub Flow

GitHub flow is simpler than Git flow, with branches being used for features and then merged back into the main branch via pull requests. 

pull request created for feature branch in github flow

It factors deployment into the equation and is used by GitHub itself to develop its site. GitHub even uses a chatbot to handle deployments.

Branches are given descriptive names that describe the work they are doing. The main branch is always deployable.

When a pull request is made, team members can discuss the changes and then decide whether to accept the merge or ask for further changes.

Pull requests create a discussion that the whole team can see, which is especially suitable for remote teams. It’s a useful way to provide feedback and guidance to new developers and is well suited to public, open-source projects.

This strategy is easy to understand and works well for small teams. It is fantastic for enabling continuous delivery and helps projects run smoothly.

As you scale up, though, it becomes challenging to manage the many pull requests. With larger teams, there are often many developers working on their own feature branches. When they try to merge them back, they can step on each other’s toes.

Even if each developer takes just fifteen minutes to lock the main thread prior to testing and merging, that can cause a bottleneck if you have hundreds of pull requests every week. If locking the main thread takes longer than fifteen minutes, then of course the slowdown will be worse. People can end up waiting all day for the main branch to become available. 

You can also run into problems if you have a release window at specific times since in GitHub flow main needs to be immediately deployable when features are merged.

There’s also the need to test and deploy from branches rather than from main, which may not suit all teams. Adding a production branch is a possible variant; it adds some complexity but gives you a dedicated spot for testing and ironing out issues. If you need additional branches, you may want to look at GitLab flow.

GitLab Flow

GitLab flow is the most recently developed strategy presented here and is designed with an awareness of the problems of the other two. That doesn’t necessarily make it better, though. 

As a strategy, it recognizes that Git flow is complicated, but it aims to redress some of the loss of functionality caused by GitHub flow’s simpler model.

GitLab flow adds a dedicated production branch alongside the main and feature branches. When features are ready, you merge them with main. The main can be merged to production when you’re ready to deploy your new version.

That helps prevent issues where development branches are left hanging because you aren’t ready to test changes prior to release. It can be helpful in teams where you have people dedicated to releases whose availability differs from that of your developers.

Development branches should be removed when you’re finished with them so that the list of branches provides a list of what is currently under development.

various branches in gitlab flow

Optionally, you can add a staging branch. This branch is automatically copied to your staging environment if you have one, which makes testing it faster and easier. You can also do this with a pre-production branch. 

For releasing software publicly, you can create dedicated release branches. These branch from main and are given a version number corresponding to the release.

To keep order, it’s common to protect the main branch so only senior developers can modify it. That way there’s less of a chance that errors may be inadvertently introduced. 

GitLab provides a detailed set of guidance in its documentation for GitLab flow, explaining best practices for everything from rebasing your repo to writing good commit messages. Reading through it is a good idea regardless of the strategy your team chooses.

GitLab is simpler than Git flow but covers more than GitHub flow, making it a good, evolved middle ground between the two. It works well for continuous integration scenarios, and its optional branches make it adaptable to your specific needs.

It isn’t as easy to use as it could be, and its flexibility means you have to carefully define how you’ll use it. Make sure your team is clear on which optional branches you plan to use.

These optional branches clearly increase complexity. Whether that’s worth the trouble will depend on how your team works.

Conclusion

The right Git branching strategy can make your life easier, enabling your team to build software safely and collaborate without breaking things. Defining your workflow helps developers understand what they need to do and gives everyone a clear set of rules to follow.

The strategies here offer a mix of simplicity and complexity. They’re each suitable for particular types of projects, so picking the one that fits your needs most closely will help keep your interactions with Git as painless as possible.

However, you want to avoid putting all your faith in the versioning systems you’re working with at any point in time. It is vital to have a backup in case things go wrong. The bigger the project, the more critical it is that you do so. 

BackHub, now known as Rewind, uses regular repo backups as well as syncing to cloud storage to help you restore your code if things go awry. For additional peace of mind, you can integrate the tool into your workflows. Rewind works with both GitHub, GitLab, and Bitbucket projects and gives you a quick, easy way to recover from data loss.

Start your free trial of Rewind.