There are many strategies for managing branches in your software development process. In The Ultimate Contribution post, I mentioned branches and merge requests, which explain a single contribution but not a collaboration between many developers. Collaboration can be organized with different branching strategies. The best one for you depends on certain aspects of your context. In this issue, we will discuss when to apply which one.
As before, my experience is mainly related to Git, so you can try to map some ideas to another VCS, but I didn’t have the intention to make it compatible.
Overview
There are no best or worst options, but there are more appropriate ones for your case.
First of all, let’s name what options are widely used:
Git Flow
Trunk-based Flow + Feature Flags
GitHub Flow
Gitlab Flow
One Flow
You might find other strategies, but I want to show you a framework for choosing the best from the available options.
We will compare and find the right place for these strategies, but first, let’s formulate properties for atoms of these approaches: Commit, Branch, Tag.
Atoms
Commit
An immutable state of the repository. The key properties of any commit:
uniquely identifies a change and state of the repository since the change is applied
immutable state
Branch
Dynamic pointer to a commit that isolates and tracks a set of changes. The key properties of any branch:
dynamically identifies a set of changes
simplifies work with an isolated set of changes
Tag
Static pointer to a commit that simplifies the detection of a particular state. The key properties of any tag:
names a state
manage static identification. For example, 1.0.0 statically identifies sources for a particular version of the component.
Before diving deep into strategies, let’s understand what properties will impact choosing the most appropriate one.
Properties that impact strategy choice
The branching strategy is a living organism that should adapt to your current context.
Team size
Adaptation means starting from the simplest option for a single developer (if that is your case) and, evolutionary, coming to the best option for a team.
Team skills
Your team's skill level impacts the choice because some strategies protect you more from beginner’s mistakes than others.
Code organization strategy
The more projects are stored inside the same repository, the more people collaborate and resolve conflicts - the more important it is to consider options that minimize conflict rate and improve continuous integration. At the same time, if you can avoid complexity because there is no collaboration, why not?
Desired frequency of delivery
Do you want to deliver every single feature available immediately and turn them on/off via feature flags, or you do mostly not care about granular feature tuning? This matters.
Strategies
Common practice is that a feature branch is short-living, so since the feature is merged, you should remove a feature branch, but at the same time, if release branches exist, they should be removed only if your context allows that.
Git Flow
There is a chance that the quantity of articles about Git Flow is more than the quantity of atoms in the Universe. The strategy is pretty mature, but the disadvantages of it are well-discovered as well.
This approach is generally good, but there is a place for some redundancy and potential inconsistency.
Every next merge will require a run of the CI Pipeline, which means that if you checked something manually, it is not guaranteed to have the same on production because, after your check, the artifact will be rebuilt again (on release → main merge) so something might go wrong.
You have two long-living branches main & develop. That potentially might introduce inconsistency, for example, because you might forget to merge back your fixes from the release branch
Team size: works for any team size, but it is overkill for a team of one
Team skills: if you have fewer QA resources than needed, a low level of QA automation, and some developers have junior-level
Code Organization Strategy: a single main branch might sound uncomfortable for mono repositories with many teams
Desired frequency of delivery: at max once a few weeks
Trunk-based Flow + Feature Flags
The trunk is your main branch (whatever you name it), a place of Continuous Integration. Developers commit their changes as early as possible and create not feature branches but branches by abstractions, using feature flags to manage what is enabled in production. Merges should happen every day to guarantee a high level of continuous integration. Watch the video of the week at the end of the issue to get more details.
The approach is super simple but requires more effort and cost to implement. Feature flags require extra infrastructure, feature flags need to be maintained, feature flag cleanup process should be in place. At the same time, you get an opportunity to perform A/B testing for free.
Team size: works for any team size (the simplest option for one developer)
Team skills: a highly skilled team and a high level of QA automation. Developers have a strong understanding of how to manage abstractions with feature flags
Code Organization Strategy: You get the most profits from mono repositories because all the code is integrated as quickly as possible. But in general both ways are fine.
Desired frequency of delivery: as soon as abstraction is available in the main branch, it should be delivered. This is the fastest strategy of delivery.
GitHub Flow
This flow looks pretty similar to trunk-based approach. But the difference is that it doesn’t require daily merges.
Team size: works for any team size (the simplest option for one developer)
Team skills: mixed team with different levels, QA resources are enough to guarantee feature quality
Code Organization Strategy: you get the most profits from mono repositories because all the code is integrated as quickly as possible.
Desired frequency of delivery: as soon as a feature is available in the main branch, it is deployable.
GitLab Flow
GitLab transforms the idea of branches into subsequent pipelines of changes. You merge feature branches to the main branch (for GitLab Flow it is the main long-living development branch), but you can also introduce any other branches you need, like “production”, “pre-production”, etc. The problem of inconsistency here is presented as well but in another form because you have long living branches for main and production.
Team size: works for any team size (but overkill for a team of one)
Team skills: mixed team with different levels, QA resources are enough to guarantee feature quality
Code Organization Strategy: does not work if many projects stored in the same repository
Desired frequency of delivery: at max once a few weeks, not more often
One Flow
This approach has some variations, and I really recommend you spend some time on the original article. The main idea is that you still have only one long-living branch and use another one only if you want to simplify navigation for bug fixes. The approach is pretty flexible and can be constructed according to your requirements
Team size: works for any team size (moderate complexity for one developer)
Team skills: mixed team with different levels, QA resources are enough to guarantee feature quality
Code Organization Strategy: appropriate for both mono/micro repositories
Desired frequency of delivery: release complexity is not high, but I’d say that it is designed for at max once a few weeks
Conclusion
Let’s review a few cases:
The best for one developer and moderate QA automation: GitHub Flow
The best for skilled teams and high QA automation: Trunk-based Flow
The best for moderately skilled teams, low QA automation, and complex release acceptance process: GitLab Flow
The best for moderately skilled teams, low QA automation, and simple release acceptance process: One Flow
There is no “the best strategy” because the most appropriate depends on your case. GitFlow is generally outdated because there are other simpler options to achieve the same results. Since you have this knowledge, you can choose or even design the most appropriate one. In the next issue, we will talk about The Ultimate Repository Configuration and get a better understanding of how to manage all these guides.
The Video Of The Week
Resources
Trunk-based development
https://trunkbaseddevelopment.com/
GitHub Flow
https://githubflow.github.io/
GitLab Flow
https://about.gitlab.com/topics/version-control/what-is-gitlab-flow/
One Flow
https://www.endoflineblog.com/oneflow-a-git-branching-model-and-workflow