As I am getting older, I noticed that my sentences often start with “back in the days”. It kinda feels like old Albert Trotter from the “Only Fools and Horses” sitcom, but here it is.
Back in the days, we used SVN as a Version Control System (VCS). The most popular client TortoiseSVN was a window into how to push and pull your code to the trunk. Wait what?
Yes, some version of Trunk Based Development was a thing a long time ago, we just didn’t give it a name. Then Git became popular as a more powerful solution, and soon enough, GitFlow established itself as a dominant branching model to organize a codebase on VCS.
Before we move on, let me tell you - this is not just another post about trunk-based development.
Trunk Based Development
All the cool kids from the block are using it today. The main idea is to use one long-lived branch and everyone contributes directly, or by merging short-lived branches into it.
Nowadays, Trunk Based Development is enabled on Git by imposing the master/main
branch as the only long-lived branch. CI/CD pipeline is set on this branch to deploy the changes to production.
Advocates of this approach will often say that this is the only way that enables true Continuous Deployment and Build-Once-Deploy-More strategy.
It’s true. The advantage of this approach is that you can push to the trunk a couple of times a day, and deploy to production at the same rate. Although unintuitive, it reduces the amount of serious defects in the product.
As a side effect, there is less operational overhead, and fewer communication lines, and eventually, the team working on the product can shrink and be simpler. That’s because in order to deploy frequently, user stories are often very small. QA process as we think of it is minimal or not existing, as developers are doing QA mostly.
As a cherry on top, the just apply different environment variables to the already-built container and deploy it to a different environment. Magic.
GitFlow (and its variations)
As a branching model, it assumes more than one long-lived branch and a couple of different types of short-lived branches.
Feature development
Main Branch (main
):
main
is a production-ready branch. The code here is stable and usually represents the version of the code that is currently live in the production.Deployments to production are made from this branch.
Development Branch (dev):
This is the primary development branch where all the features, bug fixes, or any other code changes are merged.
It's ahead of the
main
branch in terms of new code changes.
Feature Branch (feature/user-registration
as an example):
Branches created for developing specific features.
These branches are short-lived and exist for the duration of specific feature development.
They are branched off from dev and will eventually be merged back into dev once the feature is complete.
Release Procedure with GitFlow
Release Branch (release/0.9.0
)
When you are ready for a release, a release
branch is created off the dev
branch. This branch is used to prepare for a new production release. Any final adjustments (like bug fixes, and documentation) needed for the release are made here.
No new features are added to this branch.
Deployment
The release branch undergoes deployments to different environments for testing.
First, it's deployed to a Staging Environment.
Then, it's deployed to a Demo Environment.
Once everything is tested and ready, the release branch is merged into the
main
and is deployed to Production.
It's also a good practice to merge the release
branch back into dev
to ensure any last-minute fixes are incorporated into the development
branch.
Build-Once-Deploy-More with GitFlow?
A general misunderstanding with GitFlow is that every branch needs to have a build pipeline. This is especially true with the master/main
branch.
Nothing is stopping us from using artifacts built from the release
branch treating is as immutable artifacts, and promoting them across different environments.
Which one is better?
Neither and both. Set the process based on the needs of your current context. Here is a quick rule of thumb.
When to use GitFlow?
When you have a junior team.
When your release cycle is measured in weeks and not hours.
When you start a greenfield project.
The expected scope is a couple of months only.
If your team doesn’t have established a developer culture that promotes stability-before-delivery-speed.
When to use Trunk Based Development?
When you deploy multiple times a day.
Your team is composed of experienced engineers.
There is a high trust culture in the team. If you as a dev, break something simple in the production by pushing an untested codebase, you’ll break the development culture of such a team, and you’ll feel pretty bad about it. What’s more, you’ll undermine the trust given to you.
Long-running project, which already found product market fit and is stable to some extent.
When the advantages of this approach are greater than the risks of breaking something in the process.
Reality Check
How many of you are working in such a team? Lasts for years, working on a continuous product? Although I admit I am biased toward the software service industry, most people I know are changing projects on a yearly basis, or often.
Software developers with the luxury of working in the same team, with established trust, culture, and norms, and the same product are usually in big tech.
I am not rooting against any approach, but I am rooting for you not to follow the hype by default. Take wider context into consideration, look around you calculate the risks, and then make a decision.