Git Flows and modern deployment pipelines
Last year I was working on improvement of deployment pipelines for a large live application, which has as usual plenty of new features and bugs. And it’s very important in such projects to consider development flows and choose a right one according to the product and business needs. Choosing a wrong strategy can cause not only losing of efficiency but also can let dramatic bugs leak to the production.
Since we speak about pipelines, it also means not only CD but CI. But the CI topic usually boils down to the simple fact: the bug must be revealed as soon as possible. Which means: adapt Testing Pyramid and integrate the tests to your deployment pipelines. There come eventually problems with writing tests itself and their performance in pipelines, but it’s already another story.
But considering possible Git flows and choosing the right one for your needs might give a huge boost to your team.
Traditional Git Flow
The first and the oldest approach which is still very popular and legit. It assumes, that you have a master and a develop branch. Master is supposed to be deployed to production having always the stable state and develop for any possible mess except that.
To distinguish releases it suggests to use tags.
I as well as many others had made a lot of projects using this approach. And always I had that feeling, that master or develop, one of them ist just redundant. And we kept it, just because the idea
master must be always stable
But it’s some kind of nonsense. Git is exactly there to be able easily to rollback your code to the stable state. You don’t need to establish a dedicated branch for that. Furthermore, nowadays it’s very common, that you develiver not code, but Docker images, which can be build out of any commit. But anyway, once you tested your main branch and business gave a green light, you are ready to deploy it, without any merges (btw it’s one of the points from my previous article about pipeline as code and GitLab in particularly).
Besides the redundancy of develop branch, there comes also a problem with hotfixes, which is actually also caused by the same reason: merge of a master hotfix back to develop is annoying and can be forgotten.
Many criticise Git Flow also that it causes spaghetti-looking history. But it’s mostly avoidable when your teams strictly follows rules.
So summing up, the traditional Git flow has the following disadvantages:
- Additional effort (merges) due to the redundant develop branch
- Hard to plan releases. You have to deploy everything which is inside develop.
As you could guess, there is a much easier way to work with branches, which also fits very well for continuous delivery: when you work only with the master and feature branches. Once a feature is ready, it gets merged into master, tested and immediately deployed.
That’s what is also know as GitHub Flow. For me it’s the best option, when you don’t have to collect features and can make releases as often as possible. The problem is that due to nature of features (many of them are dependent) and releases (users are used to receive bunch of new things once, rather than dozens of small things during the month for example) such approach very often doesn’t really work out. But you release hundred times per day as Neflix, for example, than it would work perfectly for you.
So the Github flow has only one disadvantage:
- It doesn’t work for bunch releases
GitLab Flow and Microsoft Release Flow
GitLab tried to keep simplicity of Github flow but at the same time to introduce a possibility to prepare normal releases. So they (or Microsoft, to be honest I don’t know who was the first) came up with idea of environment branches in terms of GitLab and Release Branches in terms of Microsoft. And the same similar idea underlies OneFlow: you work on your master branch using feature branch as you would with GitHub flow, but just before your release you create a release branch (or environment branch from GitLab. They are can be multiple btw, e.g staging and production, and one is getting branched further from the previous one). Doing that you kind of freeze your code state in case the deployment can take time (e.g you are waiting for an approval from third-party provider or just test the release couple of days), so it doesn’t prevent from further development in master.
So looks better, but still doesn’t solve some principle problems that we had with our old good Git flow.
GitLab and Microsoft tricky suggest to use cherry-picking (they even made UI for that in Azure DevOps and GitLab). The idea is that you make hotfixes always and only in master, so you protect yourself from forgetting to merge back that hotfix to master. So once you made a hotfix to master, you cherry-pick it to the appropriate release/environment branch. Hm? For me it sounds beautiful and ugly at the same time.
- Coupling with the platform (cherry picking UI and deep integration of Git Flow to deployment processes)
- Still poor release planning
So what’s with release planning?
So as we could see, none of these major Git Flows suggests long-term planned releases. Long-term planned release means, that just before a production deployment there is no need to review develop/master branch, searching for feature which should not be deployed in this release. It means, that we have a dedicated branch with exact features, ready for deployment. Yes, it might be challenging to plan everything correctly, but it brings a lot of good structuring and order to the development process. It works also pretty well along with Scrum sprints and planning. Besides that, you can run 2 parallel release branches and develop independently heavy features.
So it looks like this
You still have only one main branch. Develop is needless. But unlike GitLab/MS Flow you create release branches in advance. So every merge back to master means production deployment. Of course you still have couple of disadvantages:
- You have to keep in sync your release branches with master. Once master has been actualized, you should merge it the running release branches
- You have to plan really well
There is no best and worse Git Flow, in order to choose one for your project, try to consider following points:
- How often do we you release. It can be, that releasing atomic features is completely fine for you and GitHub Flow would your best choice
- Can you more or less precisely plan releases in advance?
- Which automation tool are you going to use. GitLab and Microsoft Flows are pretty good implemented to their platforms
And don’t be afraid to experiment and adapt solution to your needs and deployment processes. All of these flows are just recommendations and ideas for consideration.