Git Branching Insights
Git is the most popular version control system and in this blog, I will be sharing some insights of using Git in a professional environment. I will review two branching strategies and share additional insights in connection with Continuous Integration and Continuous Delivery/Deployment.
Branching strategy - Gitflow
If you search for “git branching strategy” you are most likely to see the Gitflow strategy as the top most search result. So it is quite common to see many teams using Gitflow branching strategy for Git. The below picture is a high level overview of Gitflow model.
As you can see Github flow refers to many different branches - master, develop, feature, release and hotfix branches. Each of these branches have a purpose but the more relevant ones for our discussion are feature and release branches. Note that bug fixes are not called out with branches of their own in Gitflow.
Feature Branch
Feature branches are used for developing new features. While Gitflow talks about feature in general, in real life we deal with long-lived vs short-lived features. Many features may be small increments over the master implemented by a single developer. At the same time there could be features that involve multiple developers changing code in different modules.
Release Branch
Before Continuous Integration (CI) and Continuous Delivery/Deployment (CD) became popular, “releasing” software was a significant milestone. In order ensure releases meet high quality bar, release branches are created from “master” few days/weeks before the release. The idea is to fix only critical bugs and reduce code churn in the release branch.
Even in the CI/CD world, it is not uncommon to have release milestones.
Branching strategy - Github Flow or Release Flow
Microsoft uses a Release Flow strategy to deliver code changes to production. The Release flow is based on Github Flow championed by Github. This in turn seems to be modeled after Trunk based development.
The short summary of these three related strategies is as follows:
- Commit often - whether a feature is small or big, it is important to commit (and merge) code back to master. Basically try to avoid long lived feature branches.
- Commit often including bug fixes - the same logic and mechanism applies to bug fixes. Create a branch off from master and fix/merge bug fixes.
- Release from Master - Github flow and Trunk based development is more explicit about this. However, Microsoft uses “release branch”.
The picture below refers to the Git branching strategy adopted at Microsoft.
Where to fix bugs when using Release branches
Once a release branch is created from Master, it is possible that a bug fix is needed for the release. In this case we can either fix the bug in master and then migrate the fix to release branch or vice-versa.
As shown in this video - Google prefers to fix the bug in master branch first and then cherry pick the fix to the release branch. Microsoft seems to suggest the same model in their picture above (see the red topic branch). However Microsoft also has another blog/article that says cherry pick from release branch to master.
By fixing a bug in master branch first, you make the changes available to all developers. Remember developers create branches off of master and commit code frequently.
Impact of testing
The decision to first fix on master or not is also influenced by testing strategy. If you have adopted CI/CD, it is highly likely that you have invested in test automation. This means that automated testing of new feature happens along with the development. This means that your master branch is running more test cases when compared to release branch. Therefore by fixing the bug on master branch, you can test much more scenarios around the bug fix. Once the fix is cherry picked to the release branch you will still have to run some regression tests but that should be a much smaller subset of your test suite.
Importance of feature flags
With the trunk based development, a feature is broken into large number of small commits to the master branch. So the code for a new feature exists on the master branch even though the feature is not officially code complete. It is important to protect master branch functionality from the new feature (partial) code using feature flags.