Branching strategies

Eduard Bargues
7 min readJan 28, 2021

--

Why Git-Flow might not be the best idea for you

Icons made by Pixel perfect from Flaticon.

Introduction

Every time a new team is assembled, we need to think about how teammates are going to work together. Share code, testing stages, deployment gates, … A bunch of technical words start appearing during (long) conversations where everybody is eager to provide his opinion.

When a project is about to start there is a lot of uncertainty and is difficult sometimes to know the requirements. Also, the team doesn’t know how the best way to develop is going to be since the number of people involved might change very soon. In that context, trying to come up with a unique branching strategy can be a waste of time for you and your team.

In the following sections, I’ll present all the different branching-strategies that a team can come up with during its evolution (Or at least the ones I deem important 😊). From a single developer to 10+ developers working on the same project, I’ll be showing step by step the whys and what-for of the different strategies presented here.

Starting the project

Your boss tells you one day that you better start thinking about this new app or service for a future client. For the moment, you’ll be the only one working on it but expect to welcome more teammates once the project gains some momentum.

Commit to your local branch and push it to the origin repository.

At this point, there is no need to complicate things. You work alone, so there is no need to go beyond working in a single branch (let’s call it the main branch) and pushing from time to time.

More developers join

So, seems the company is starting to move towards your project. Your app name starts popping up on several meetings and they (don’t know who) decides to add several extra developers to help you. Obviously, good and bad news come in pairs so that means you have a deadline coming right away 😁.

You realize several people will be working on many different features (or bug fixes) at the same time and decide to add some control and order to your project.

Developers work in dedicated feature/* and bugfix/* branches and merge their work to the main branch through pull requests

You agree to use dedicated feature/* and bugfix/* branches. Each developer creates a branch from the main one and starts developing. Once the work is done, a pull request is created and the developer gathers a couple of approvals among the team. At the same time, a continuous-integration pipeline runs against the code performing some tests.

If the developer has enough approvals and the CI pipeline is green the pull request can be merged.

First contact with the client

You are doing a good. You did some inside demos and seems that your team could have an MVP ready in a matter of weeks. Your boss tells you that a client might be interested to check the MVP and asks you to deploy it in an environment your client can access.

Easy 😀! You decide that every merge to your main branch will deploy the code and expose it to the client. Shouldn’t be that hard.

Each merge in the main branch triggers a deployment that compiles and exposes the code to your client.

Omitting the details about the pipeline implementation, you have now embraced continuous deployment! 🎉

A new client wants to use your app

So far your team is working great. They adapted quite fast to the current branching strategy and your client seems to be enjoying your time to market.

You are doing so great that a new client comes and asks to start using the app. Obviously, your boss immediately says yes. Also, this new client wants features the previous one didn’t ask for so you immediately realize that you’ll need to support several versions of the app in production.

Dedicated release/* branches that contain the several versions your app supports.

Your team decides to get rid of continuous deployments and have dedicated release branches where each supported version of your app will live. That way, by creating a release/* you are able to trigger the deployment of a specific version.

The only thing problematic at this point is that you need to keep track of the versions you are supporting based on what your clients are using. It is not a big deal if done right but something to consider. Also, note the approach you are taking now is quite similar to what GitFlow proposes.

The first bug in production

Your work is amazing but one of your clients finds a bug. You immediately start investigating. Your team creates a hotfix/* branch from the release branch your client is using, develop the solution, merge it back and deploy it right away.

Create a hotfix/* branch from release/*, fix it and deploy such bugfix.

Also, don’t forget to update your main branch with the same hotfix (and all the release created after the one you fix) so future releases have the fix.

After the bugfix in production, you analyze what your team had to do:

  • Create hotfix/* branch from the affected release.
  • Merge the hotfix and deploy it to so the client has the fix.
  • Update the main branch with the fix.
  • Update any release that was created after the one you fixed.

😟Okay... That seems a lot of work to do. Also, you realize that next time you could be dealing with a serious bug and your clients can not wait for you to fix it (and replicate such fix to all the release branches you may have). There must be a better way to manage that 🤔 …

C.Integration + C.Delivery + C.Deployments

So you start studying better branching strategies and you start stumbling with words like artifacts and continuous-delivery in several articles. You realize that you don’t know the difference between cont. delivery and cont. deployment and you wonder if you are missing a piece of the whole picture 🤔. Is there something beyond GitFlow?

CI + C.Delivery + C.Deployment all together!

Well, it turns out there is! 😀 After some meeting with your team, you all come up with what seems to be the definitive solution that best suits you. The approach is:

  • Features and bugfixes will be developed in feature/* and bugfix/* branches from the main branch. They will be created, developed, and merged back using a pull request where the continuous integration pipeline will be launched.
  • Immediately after the merge, a pipeline will create (and tag) a new version in your last commit. Then, your code will get compiled and packed. This package, called artifact, will be stored somewhere so that you can retrieve it during a deployment.
  • Just after that, deployment of the last version will be triggered. The artifact will be retrieved from the storage and directly deployed.

There are several advantages of this approach:

  • Your time to market gets drastically reduced. Deliveries and deployments happen as you merge your code.
  • If a bug is found, you can safely roll back to the previous version of your app while you look for a solution. That way, your clients can keep using the app.
  • Your whole flow gets simplified a lot. Now each client can use a different version and you don’t need to maintain several release branches.

Conclusions

We’ve been through a (fictional and short) story of a development team. From being just one developer to 10+ people working on the project.

The requirements of the project and needs of the team have changed while the team was evolving so different branching strategies were required. We only grasp the surface of the possibilities that you, as a team, can do to manage your software development cycle.

I think that the most important lesson here is to know the problems your team is trying to solve. Implement the simplest possible solution at any given time and keep the continuous-improvement loop in motion. You most probably end up with a different solution I present here (But with the right one for you❗😄).

In my current team, we are now using a C.Integration and C.Delivery and our deployments happen once or twice a month. No continuous deployment in our case 😊. The business requirements have also need to take into account. There might be clients that are not able to absorb new versions as fast as your team develops them and require a steady release cycle where they can predict the next versions in advance.

--

--

Eduard Bargues

Proud teacher-volunteer at Migracode and DevOps-engineer at ohpen.com where I keep pushing my AWS+Serverless knowledge every day.