This post describes a simplified Git branching strategy to software versioning and release. This strategy is a slightly simplified version of GitFLow. This strategy does not contradict GitFlow in terms of software development (you can still use feature/* branches), but rather a slight deviation on the release side of GitFlow.
This branching model is a recommendation to the existing GitFlow for a simpler software release cycle. This model is unbiased in terms of the development workflow, as long as you have a development branch you can use this strategy. If you know GitFlow already, this strategy is simply a slight deviation of it with the removal of hot fix branches.
The development (Dev) branch consists of the latest development commits. Feature branches can be used, but must be merged back to the Dev branch at the end of the day for consistency. Continuous intergration (e.g. running of unit tests) should be implemented on every commit/merge to Dev.
Release Candidate Branch
The Release Candidate (rc) branch is always branched off Dev and is only carried out when the team agrees on a release. Once a Release Candidate branch is created, no more features can be added to this branch, only bug fixes and minor fixes can be carried out on the branch. Release Branch names have the prefix rc followed by the version number (semantic versioning without the patch). Extra features can still be added to the Dev branch.
Continuously merge back to Dev
Commits on the Release Candidate branch (i.e. bug fixes) should be continuously merged back to Dev, so that fixes are reflected in Dev and is available to other team members. Continuous Integration pipeline should be set up to monitor the tip of the Release Candidate branch.
Master as a collection of stable merges
The Master branch must be treated as your single branch of stability. After critical bug fixes and other minor modifications on the Release Candidate branch are complete and a release is imminent, you can merge into Master.
Master will only contain merges from Release Candidate branches. Each commit will be associated with a version tag prefixed by v and followed by the full version number (semantic versioning). Each commit/merge on Master is a stable version in production. Continuous integration pipeline must be set up to monitor Master and should be triggered on each merge to Master.
Fix on release candidates
Hot fixes in production are done on the Release Candidate branch that references the version in production. This deviates from GitFlow in that hot fix branches are not used. Once all the bug fixes are completed on the Release Candidate branch, the Release Candidate is then merged back to Master and Dev with a new version tag (Patch).
Rinse and Repeat
When a new release has been decided by the team, a new Release Candidate is branched off from Dev. Once a minor version has been merged into Master, the previous Release Candidate branch becomes obsolete and may be safely deleted.
This branching strategy ensures that the Dev branch is always cutting edge and at the tip of development and the Master branch is the source of truth and stability. This offers a clean and maintainable git repository since at any given time there are only three main branches. Continuous Integration and Continuous Deployment is made easy with this branching strategy as Release Candidate branches are prefixed with rc and the tip of Master is always the latest stable release.