A Scaleable Git Branching Strategy

If you aren’t using git, you should be. If you aren’t using branches in git, you’re doing it wrong. Git, amongst other things, is incredibly powerful when it comes to branching. The popular strategy first documented by Nvie nicely creates some convention around how to take full advantage of this power. The problem is that the original nvie model is great for private, personal projects, but as your team grows and the complexity of the project increases, the limitations start to manifest themselves as bugs, merge conflicts and confusion as to where a commit belongs or which branch a build job should be building. However, below I will explain how I have taken the brilliance of the Nvie model and fused it with some existing software development concepts to create a model that also integrates nicely with the newer agile project management practices such as SCRUM.

In the 2010s you should already understand the benefits of the time honoured software development concept of alpha and beta versions (aka develop and staging) and the newer concept of continuous delivery. Leveraging the benefits and power of git to interact with the support systems that are fast becoming standard in modern, large scale, ongoing projects. Systems such as: Continuous Integration (Jenkins), agile tools (JiRA, Trello), internal app distribution (HockeyApp/Google Play) start to become important on larger ongoing projects (because you need to start o automate your interactions with people and teams outside your own: QA teams, product managers, designers and your average “Hey Joe, have you finished … yet? Where can I get the latest version to test?“) and git has a central role to play when interacting with them.

What is an alpha/beta version?

Alpha and beta product streams are a time honoured concept in software development (actually the concept is usually just hiding in modern times under the guise of staging and develop). Android Studio and gradle let you produce these versions elegantly using buildTypes, Enrique López Mañas has a great post on how to do this.

Being a part of the beta or alpha user group of your favourite piece of software is, as an end-user, a privilege because you have the goodies before the average user. Google releases a ‘preview’ version of their SDK a few months before it releases the actual release, Apple does the same with its developer previews. Apps like Spotify also quietly announce requests for beta testers. Search around the website of your favourite app and see if they have an alpha or beta user group, you may be surprised.

I hear you say, “But alpha and beta is an old ‘waterfall’ concept, how do we squeeze that into Agile methodologies and Continuous Delivery?” First of all, it’s not a Waterfall concept at all, and secondly, there will be no squeezing of concepts into places they don’t belong. Alpha and beta releases are an independent idea not directly related to project management but rather a concept used more in software development itself to compartmentalise project releases.

Three product streams, three branches

The alpha branch is where new features are committed. Adding new features inevitably destabilises any piece of software because it adds uncertainty. This is why the alpha product stream is always considered ‘bleeding edge’ — it has the coolest new features, but it may behave strangely or unexpectedly crash.

The beta branch is where bug fixes and only bug fixes are committed. It is undergoing stabilisation. ALL bugs are fixed here first.

New features destabilise the application, bug fixing stabilises it.

The production branch is for hot fixes only. Hot fixes are fixed in the production stream since they are ONLY small changes with low risk and huge benefit. eg. fix a config file so that the product can talk with the backend services and start working again!

Integrating with Continuous Integration

Each product stream (alpha, beta and production) has its own branch in git, with a CI build monitoring the branch. Any git host (GitHub, GitLab, Bitbucket) worth its salt will provide web hooks that will notify your build server and initiate a build, or you can just be boring and poll the repository…

The CI job can do hundreds of amazing things but for the purposes of this new branching strategy these must include:

  1. generating the perfect versionCode;
  2. building the app’s apk;
  3. pushing the app up to a distribution host (HockeyApp) for the QA team and alpha/beta user groups;
  4. tagging the commit that was just built with the versionName that appears in the app somewhere.

The last point is important because it allows you to trace a reported bug back to a single commit. There are many ways to do this but tagging is the one that works best for the combination of users/support teams/testers and developers.*

Synchronising branches

The most complex part of this process comes at the end of a sprint cycle when it’s time to synchronise these three branches. I prefer to do this with the entire team present, this cuts down on the possibility of accidentally incorrectly resolving a conflict of some kind because all conflicts are solved by the team as one.

You can see that after a sprint, production, beta and alpha are very different. Three things need to happen:

  1. we need to release the new version (make beta the new production),
  2. we need to make alpha the new beta and
  3. we need to make sure that the hotfix and bug fixes make it into both beta and alpha.

Pro tip: Perform the following in your local repository and then when you have checked and double checked that everything is in order, push all three at the same time.

The first step is to merge from left to right (production into beta, then beta into alpha), this ensures that all the bug fixes propagate down to the alpha. This can actually be done at anytime, but must be done at the end of a sprint.

After merging from left to right, we merge right to left. Beta to production FIRST, then alpha to beta, essentially shifting the branches over to the left.

This sounds confusing in writing, the video at the top demonstrates this far more elegantly.

Once this is done, still using your local repo, double check that each branch clean builds and has the correct versionName. This means checking that the production versionName (1.7) is one behind beta (1.8) who is in turn one behind alpha (1.9). Note that alpha’s build.gradle must be manually edited to increment to a brand new version.

This method requires advanced knowledge of git and also requires everyone on the team to understand the process. This means that when you implement this for the first time there are going to be mistakes. Whoever understands the process the best needs to be the champion of the system and gently correct any deviations. Remember, you are using source control so it is very hard (not impossible) to completely lose work so don’t be frightened.

Summary

The benefit of this model is that it allows you to continue to work on both bugs and features at the same time, but separately. This ensures that your new features have a stabilisation period before they are released, and also that you have a regular and stable release at the end of your sprint cycle.

Click here to download the Android Branching Strategy keynote source file


Originally published at www.androidshortcuts.com.