Git branching strategy to achieve continuous delivery

Continuous delivery is a very common software delivery practice. There are many articles and same terminology used in different meaning. Though it’s a generic software delivery practice, let’s think from a version control and branching strategy perspective.

Photo by Felix Mittermeier from Pexels

It would be awesome, if we could have a git branching strategy and team discipline which helps in achieving following dream goals:

  • Project manager, Delivery manager or the business doesn’t push the team to release the feature

Environment branches

Environment branches are quite popular and many teams already follow. The core concept is to have dedicated branches for different environments, for instance:

  • development / master branch

It is up to the team to decide the meaning and usage of these environments. Having more environment branches is a pain if we like to achieve true continuous delivery. We will address this in later part of this article.

Branching strategy

There are many possible ways for the team to arrive at what works best for them. Following is one such way which got matured over time and proved useful.

Simple example

production branch — everything starts and ends here

  • Any new feature branch is branched out from production

Prefer less intermediate environments

In a pure continuous delivery team, just one intermediate environment for testing works wonderfully.

  • Less intermediate environments forces the team to use shared environment optimally and keep moving features to destination (production).

Feature branch

Two features developed in parallel
  • Feature branch has just production + this feature related commits
Another example with more environments

Handling conflicts while developing overlapping features

This by itself is a signal that the feature priority is not done right. In a short lived feature branch strategy, why are two related features developed in parallel. Can the second feature be started after the first feature is delivered ? If yes, that’s the best to prioritize related features one after another. Remember these are features that are built in small chucks and get released incrementally. This pushes the team to slice and dice the feature so that it can be released in smaller chunks.

Let’s say, if it can’t be prioritized later and need to be developed in parallel, it should be handled by over the table discussions, which caused the breakage in qa etc., In this flow, let’s try to do QA for both the features together and release them together.

No more feature promotion to different environment branches

Many teams follow promoting features to different environment branches and finally reach production.

Typical promotion of features

Disadvantages in this approach:

  • feature conflicts arises on environment branches which already has other in development features.
alternate approach

Instead

  • merge the feature branch to qa
git checkout production
git pull --rebase
git push origin production:qa --force
  • If too many branches are in qa which are not yet in production, it is a signal that team should work towards making quick releases, qa/testing team should unblock them. As we see, team’s focus & thinking should be towards making releases. Either release the feature or stop blocking others. If a feature is unstable for a long time, QA branch can be force rebased from production branch and have only the next feature in queue. Once the feature is stable again, developer merges it with QA.

Signals and practices

  • anytime production branch can be compared to qa branch to identify which features are in qa and not in production. If there are too many features or changes., it’s a signal that QA is becoming a bottleneck. It gives team an insight and a chance to take corrective action
To create draft pull request in Github

No master branch or development branch

By having a branch dedicated for all the development work defeats the purpose of continuous delivery. That’s why production branch should be the only point of reference. Literally features are developed for production and not for just for the sake of development. By avoiding a branch for development, we force the developers to target production and move feature towards it. Or else, no one is going to use that feature.

Database migration and rollback strategy

If we adopt this kind of rigorous continuous delivery style, then first few steps would be build the safety net, especially about the data.

  • These risk are always there irrespective of a rigorous continuous delivery or normal delivery. But CD helps in bringing in the best practices.

What should we do when we just start a project

Courtesy: https://medialoot.com/item/free-coming-soon-template/ — Used for educational purpose
  • A simple coming soon webpage with a notify email can serve as a start, if team agrees.

How this differs from Trunk based development

IMHO, Trunk based development is too rigid and GitFlow is too flexible. The approach that is talked in this article tries to pick best parts from Trunk based development(TBD) and GitFlow.

If team has 100% automation testing (Unit, Integration and End-to-end) and if the test passes, team is confident to release, then Trunk based development is a good match. Though it’s not impossible to have a 100% automation testing in place, in reality, it is not the case in many projects. Either we don’t have enough test or we can’t guarantee the stability of the application with existing tests in many projects.

In a typical Trunk based development, parts that complicates the flow:

  • Need for 100% automation testing to promise us nothing is broken. In contrast, with above branching strategy, it gives us a stop gap environment (qa or staging or uat) to deploy the in-progress version and manually validate the functionality end to end.

Good parts in TBD:

  • One branch which will reflect the production state. All feature changes starts and ends here. In the approach that we discussed, we try to bring this practice. Just the name of that branch is ‘production’. In TBD, they refer this as ‘trunk’ or ‘master’

Need for Continuous integration and deployment flows

The approach that is discussed here, depends on following

  • Feature branch automatically creates Continuous integration pipelines. This is possible with multi branch strategy pipelines supported by most CI solutions (both hosted and on-premise)

Summary

Initially there will be mental blocks for us to adapt this approach. Especially if we are coming from features getting promoted to different environments and finally reaching production. But once we try this out for couple of iterations, it is for sure hard to go back to old ways. Just like it was hard to move from SVN to GIT and once we moved., now going back to SVN kind of version control is very hard.

There will be little more effort and discipline involved from developer side in resolving merge conflicts and keeping feature branches in sync with production. But these brings in good practices to release features quick and stop delaying the release. Over a period of time, making multiple releases each week becomes a norm.

References & additional reads

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Sairam Krish

Software Architect ★ Data engineer ★ Committed to improve data science productivity