There are all sorts of Git branching strategies you can find on the web. Instead of just picking one that seems applicable, I wanted to find out what would make me pick one over the other. On what elements would I base my decision to choose a particular branching strategy. In this article, I show you some examples of branching strategies. There is nothing new about these and they probably have some fancy name somewhere on the web. But what I want to show you in this article are the elements I think are important to base your decision on. If none of these branching strategies completely fulfill your needs, then I hope it gave you and your team at least some food for thought.
Table of Contents
The feature to main flow
This branching strategy is the most simple one and popular among DevOps enthusiasts. In this scenario, a team of developers are continuously developing and delivering new features. The goal here is to keep the time it takes to get a new version of the application in production to a minimum. To make this possible, a CI/CD pipeline gets triggered after merging a feature to the main branch. When the CI/CD pipeline starts, it builds and tests the code first and then deploys the application to production. In the example below, the CI/CD pipeline does a little bit more. After building and testing, it first deploys the application to an acceptance environment. When the customer finishes his acceptance tests, an approval is given to the CI/CD pipeline to deploy the application to production.
You can use this branching strategy in situations where you can automate the entire build, delivery and deployment process. However, if there are some time consuming manual actions required by you or someone else, then you might need a more planful delivery process. Read on to see how release branches can help you with that.
The main to release flow
This branching strategy can be used by teams that are continuously doing development work on an application, but want more control over the delivery and deployment process. It works almost the same as the Feature To Main Flow, but with the extra benefit release branches can offer. Using this branching strategy, you also maintain the benefit of having an up-to-date main branch. That is because features branches are merged to main just like in the Feature To Main Flow. The difference is there’s no delivery or deployment happening from main. That happens from the release branch.
In the example below, the CI pipeline gets triggered on each pull request. If the code builds, all unit tests have passed and a code reviewer gave his approval, the code is merged to main. At some point in time, the code in main is ready for release and a release branch is created. When everyone is ready, the CI/CD pipeline on the release branch is manually triggered to deploy the application.
Reasons for using this branching strategy
You might still be wondering why you should do the extra ‘working with release branches’ part. Well, maybe you are not in a situation where you can automate the entire delivery and deployment process. For example, you might depend on a database administrator to execute some scripts. Although technically these actions can be automated, due to organizational constraints you might not be able to enforce this. So in this situation, you will have to wait till the database administrator has time to help you out. By working with a release branch, you can prepare and plan the release with all the required people while your team continues further development on the main branch.
Another reason you might want to work with release branches is if you depend on time consuming manual actions like acceptance testing by the customer. If your release is ready and deployed in the acceptance environment, you cannot expect the customer is always ready to test the new version. Perhaps the customer is occupied with other important work and you will have to wait. Also in this case your team can continue further development on the main branch while waiting for feedback from the customer.
I also want to emphasize the benefit of continuously merging to main, which I think works best in continuous development scenarios. If you are working in a team that works continuously on expanding the application with new features, you might not exactly know which of these features will be available in the next release. Because what will be in the next release depends on the programming speed of your developers and the definition of done. For this reason, you create a release branch at the moment the main branch is ready for release.
The release to main flow
This branching strategy can be used by teams that plan beforehand which development work will be part of the next release. As you might have noticed, the difference with the Main To Release Flow is the way of working is reversed. Features are first merged to the release branch instead of main. For example, let’s suppose you work in a Scrum team that works with 2-week sprints. After sprint planning, you create a release branch for this sprint. When you and your team finish development on some feature branches, they are merged to this release branch. Then, when the release is ready, the CI/CD pipeline is manually triggered to deploy the application to the acceptance environment. When the customer finishes his acceptance tests, an approval is given to the CI/CD pipeline to deploy the application to production. Finally, the release branch is merged to main.
Note that the main branch in this strategy represents the code deployed in production. That’s different from what the main branch represents in the Main To Release Flow, where main contains the latest stable developments.
Reasons for using this branching strategy
So why should you choose to work with the Release To Main Flow over the Main To Release Flow? Well, it depends on the situation you are in and how you want to work. If you work in a team continuously doing development work on an application and you do not want to stop the development work while waiting on feedback from the customer, then the Main To Release Flow might suit you better. But, if you are in a situation where there is no continuous development work. Where you only have to do some small changes once in a while that you want to bundle in a single release. Or, there is continuous development work, but you plan this work in 2-week sprints. For these situations, the Release To Main Flow might be easier to work with.
And of course, you want to use a release branching strategy like this for the same reasons discussed earlier. If you need a more planful deployment process because you depend on time consuming manual actions. And when you can only deploy when all people required in the process are available.
Conclusion
Using the Feature To Main Flow, it is possible to achieve continuous development, continuous delivery and continuous deployment. The goal is to keep the time it takes to get a new version in production to a minimum. It is the most simple branching strategy and popular among DevOps enthusiasts. If your situation allows for it, then make use of it because the benefits of automating the entire deployment process is huge.
However, if your situation does not allow for continuous delivery and deployment, and you need a more planful process, you might be more interested in one of the following release branching strategies:
- Main To Release Flow
- Release To Main Flow
Using the Main To Release Flow, it is possible to achieve continuous development, planned delivery and planned deployment. For example, while you are preparing a release with all the required people, perhaps waiting for some to respond, your team can continue further development on the main branch.
But, if you are in a situation where there is no continuous development work. Where you only have to do some small changes once in a while that you want to bundle in a single release. Or, there is continuous development work, but you plan this work in 2-week sprints. For these situations, the Release To Main Flow might be easier to work with.