Git Workflow & Branching strategy: Best Practices

Once we start using git, it is crucial that we get the branching strategy and workflow right as soon as possible. Like many, I and my team learned it over time and in a hard way. Here I am consolidating all the Git workflow best practices that I learned over time. I hope this would help teams new to Git in finalizing their Git workflow and branching strategy.

The Background

As many organizations are migrating from various Version Control Systems (VCSs) to git, many of us are going through the learning curves. Git seems easy to from the first few days of reading. Knowing that git is one of the best version control systems and has been tried and tested by the biggest and the baddest in the industry, we all give a go. Existing source code repositories get migrated to your organization’s version of the enterprise git hub.

Developers starts to play with git. Some organizations created 2 repositories: one test and one prod. Good thinking!! They test things out in test; mostly the tests are basic, the things that are there in the first few chapters of any book on git. And then the team decides to start working on the production repository and give away the test repository. Developer’s confidence!!

Now the fun starts, the team tries to do the things they are used to in their old VCS. Soon realize that they need to understand git more. They need to understand branching more. They need to understand whether to branch or not to branch? Is branching a good thing?

Because of their past habits, some of their initial intuition was to work on master. Then someone read about having few long-running branches, suggested using them; So they created a release branch and a development branch.

By now the team has read about branching, git workflow, and how open source projects work. Everybody has their own understanding of the git world. There are meetings happening on how to define their git flows; people are coming up with different scenarios and possibilities and evaluating if their workflow supports it. Even at this point the team is not 100% sure but takes a leap of faith.

I and my team has gone through all these and finally stabilized our git workflow, created our own guidelines, identified best practices and refining them as an when needed. As it took us some time to finalize and stabilize the workflow, I thought it would be a good idea to document our workflow with the intent that it will help someone new migrating to git.

Our git workflow:

There is no specific names to our workflow, it’s of a simplified Git Flow. Our git workflow is meant to support the below-mentioned requirements. If your requirements are similar then our workflow is a good starting point.

Release practice & Team: The requirement

  • Multiple releases in a year, the time between each deployment is more or less fixed and can vary from 1 to 3 months.
  • There can be emergency releases or break-fix releases from time to time.
  • There will be times when the team needs to work for two releases. One in near future and one post that.
  • Our team size is less than 10; very closely knit. Mostly each developer work on their own story.
  • The team is distributed
  • Every code should undergo a manual code review.
  • Every night, all our unit and component test should get executed using the latest checked-in version
  • When we deploy code in test environment there should be a provision to go back to the previously deployed version in git.

Workflow & branching strategy

To support these requirements, we kept two long-running branches master and development. At the start, we branched out of master to create the development branch. They were identical at the beginning.

We give all deployments only from the master branch and all development will happen using the feature branch, branching out of the development branch. Feature branches are short-lived and will be merged onto the development branch once the work is done. If possible delete the feature branch after it gets merged onto development. This will help in avoiding a branch explosion in your repository.

Always use a pull request to merge a feature branch onto the development branch. Pull requests are reviewed and merged by a reviewer. The reviewer can give her/his review comments on the pull request through the git hosting site (GitHub, GitLab, BitBucket, etc.). After a feature branch is successfully merged onto the development branch the reviewer should delete the feature branch.

The nightly execution of test cases is done using the development branch. Once we are satisfied with the version and get ready to give a deployment, we merge the code from the development branch to the master branch. Before packaging, we always create a tag on the master branch with the version number to be used in the package.

Handling Special Situations

That’s all about the basic workflow. Now let’s talk about handling special situations.

  1. We are in the middle of a release and a bug got identified in the production code. Here middle of a release means our code for the next release is already in test environment. Based on the strategy we applied master branch is having code from the next release. In this case we need to use the tag from previous release and create a bugFix or hotFix branch. This is where the tag comes handy. Developer can now work on this branch, do their testing and give deployment from here. At the end we need to ensure that the changes done for the fix are merged back onto the current development branch.
  2. While we are working for the Nth release of the year, part of the team needs to start working for the N+1th release. This will need the team working on N+1th release to create a new development branch out of current development branch and start their work on top of it. Let’s call it N+1_development branch. Their feature branches will be on top of N+1_development. they are not allowed to merge onto master. From time to time the team will have to pull the changes happening in development branch into their N+1_development branch. This will ensure that there are no merge conflicts and if there are any it is resolved as soon as possible.

After working with this workflow for some time, I found that there is a need to enforce some rules. Like:

  1. Don’t allow direct commits in master & development branch
    • This ensures that untested codes cannot get into production
    • You can implement this through client side git hooks
  2. Merge onto development branch should be allowed only through a pull request
    • This ensures that all codes are getting reviewed
  3. Enforce pull request review before every merge

I wrote this blog sometime in 2020 and today is Feb 2022, during this time I have seen & learnt many things. One bad thing about the above approach: we are maintaining the feature branch on the main repo. Even though it gives every one a picture of what going on and who is doing what, but people tend keep these feature branches even after they have fulfilled their needs. Very soon you will have multiple abandoned branches, and some developer will start sending emails or run behind other developers to clean up all old and abandoned feature branches.

The best way to avoid these feature branch explosion in your main repo is to ask all developers to fork the repo and work on forked repo. Let the developers maintain their own forked repos, they can have as many abandoned branch as they want. This way we keep the primary repo clean. To push a code the team members need to create pull request from some branch of their forked repo to the main repo.

For more comprehensive list of best practices, check below post.


Feel free to point out issues with this strategy.