Using Git is very common among developers nowadays. But, how do you work together on Git? What is the best strategy when it comes to discussions about trunks, mono-repos and what-not? Well, let's dig into this.
Git is a free and open source, distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
Git is used in many companies, hobby projects and Open Source projects. You can host your own server or use one of the hosting platforms. In the articles "Git - Getting Started" and "Git - Next Steps", we tackled the basics already.
Overall, Git can be considered the most popular version control system.
Before digging into details, let's answer the question: "What is a Git Strategy anyway?".
Well, working with Git on your own (alone) can be summarized as
git push. But what about working with multiple developers on the same project, maybe hundreds? It will become complicated quickly, if you don't come up with some kind of strategy.
A Git Strategy (also known as Branching Strategy) makes merges predictable, allows CI/CD based on branches, pushes and merges and much more. The "Git - Next Steps" article discusses branching in general, briefly.
Depending on the type of project, the contributors working on it and other factors, you might choose one of the below or come up with your own adoption.
Git Flow is the oldest in our list, but also very popular. It was adapted by many projects and I have used it, too. At first, it might seem complicated, but it is also very flexible.
In general, it works with some branches like this:
- main branch
- develop branch, which contains the latest development
- feature branches, which are derived from develop and must be merged to it
- release branches, which are derived from develop to prepare a release and must be merged to develop and main
- hotfix branches, which are addressing bugs for a release and must be merged to main and develop
This branching strategy has some benefits when it comes to long-term support. The release branches will live as long as the release is supported, and hotfixes will be merged on the go to all relevant branches.
Doing long-term releases, which may have overlapping support cycles, requires a bigger team. The process allows these big teams and the required overhead can be spread across multiple contributors. These contributors need some adoption and experience in development, but then it works fine.
You can read way more details about this in one of the earliest articles about this strategy.
GitHub Flow is very common for many smaller projects. It is quite simple to adapt, but does not have any idea of long-term releases. Instead, it focuses on continuous deployment. This means, a bug will be fixed with the next release/tag, but not for a previous release.
It mostly consists of:
- feature and fix branches, which are always merged to main
- tags, that are made exclusively on main
Very often, Semantic Versioning is used to indicate if a new release is breaking, provides new features or similar. Since a tag will indicate a release in most cases, it is possible to have multiple features and bug fixes merged, without ever setting a tag.
Furthermore, it is very common to rebase branches before merging and delete them afterwards.
GitHub itself also provides documentation with some more details.
GitLab Flow has a completely different intention. It focuses on GitOps/DevOps workflows. Therefore, you will have branches that reflect different stages like test, stage and production.
In general, this may look like:
- main branch
- production branch, which is "live" for customers and will be merged back to main
- pre-production branches, which are derived from main and will be merged to production eventually
You can add as many pre-production branches as you like and also different production stages.
Since GitLab integrates CI/CD and other automation mechanisms, this makes it easy to work on something, push it through different stages and finally deploy it on production.
You can read more about this strategy over at GitLab.
Trunk Based Development
Trunk based development works very much like GitHub Flow. But, instead of working on a feature as long as needed, developers will merge changes on a daily basis.
Normally, it consists of:
- temporary branches, which are merged daily
This requires, that the main branch is always in a working state. One can achieve this with different mechanisms like merge rules/automated testing on merge, feature flags or another option to enable/disable code that is in development.
The method is very popular on some projects, but also requires some tooling around it to ensure that no broken code is merged to main.
There is a more detailed documentation, for sure.
Links & Docs
For your convenience, the upstream documentation.
As you can see, there are many different ways to branch and merge your code. If you ask me for a summary:
- GitHub Flow is the easiest one
- GitLab Flow is a cool option for continuous deployments with stages
- trunk based development is very straight forward, but requires some thoughts for the application and tooling
- Git Flow is very good, when it comes to long-term releases and large teams
Soooo, which strategy do you use? Is there something, I have missed, and you want to add? Please let me know!