In this post I will describe the Git branching strategy that we use. This “model” consists of a set of procedures that the development team must follow to manage our development.
This model is based on a number of assumptions on how our development is setup. When these assumptions change our branching strategy (and CI/CD) could need to be revised. These are the assumptions:
- We use C#, Git, TeamCity and Octopus Deploy
- A small team (2 back-end devs, 1 front-end dev, 1 tester)
- Development of a multi-service oriented project in one visual studio solution
- We have 4 environments; Development, Test, Acceptance, Production
With these assumptions we came up with a Git branching strategy that uses the following branches:
These branches are linked to TeamCity, our build server, to build, test and create the artifacts ( the deploy-ables) and NuGet packages. This is described in another post.
Semantically, we have main branches and support branches. The main branches are always there. The support branches are used for parallel development between team members, feature development, prepare production releases and to fix production issues. The essence is that one part of the team can continue current development on the development branch, while another part of the team is preparing, i.e., a quick production fix in the hotfix branch or prepare the upcoming release in the release branch.
The master branch holds the latest stable production version and is always deploy-able.
We tag the master branch with the different versions that have been deployed.
Active development is done in the development branch.
In feature branches we develop the new features for a future release.
A feature branch is taken from the development branch and must merge back into development.
The essence of a feature branch is that it exists as long as the feature is in development. When the feature branch is merged back to development this feature is added to the upcoming release. When the feature branch is discarded it will not see the light of day (i.e. failed proof of concept).
Naming convention: feature/*
The release branch is used to prepare the production release. We do last-minute dotting of i’s and crossing t’s. also we do minor bug fixes if needed and prepare what needs to be prepared (version numbers, release notes, etc.). We do not add new functionality.
With the release branch created, development can continue with the next big version/iteration and in parallel we continue with finishing the release for production.
Release branches branch of from development when the iteration is done and must merge back in master and development.
When the release is deployed to production a few things happen
- We merge the release branch to the hotfix branch.
This prepares us to act fast when we need to fix production issues.
- We merge the release branch back to development.
This makes sure all coding, fixes, etc. we had to do for production are also in the new release.
- We merge the release branch to master.
This makes sure our master holds the latest stable version.
This merge is tagged with the version number
A hotfix branch branches from the release branch after going live and must merge back to development. This safeguards that the fix is included in the next release as well.
All these branches are linked to TeamCity, our build server, to build, test and create the artifacts ( the deploy-ables) and NuGet packages. This is described in another post.