dev -> release-candidate(staging) -> release
I had some initial thoughts on how to approach the subject but I've also considered having a look online to see what other people have written about the subject. I found two articles:
Considering these two articles, and having in mind that the 'master' branch should be the almighty development branch, I took the second approach.
For this I went out in testing on how exactly everything should fall into place, and more exactly:
- how code should move from one branch to another
- how a single commit can be moved from one branch to another in case of a hot-fix
Merging code from one branch to another
Branching direction is always going to be: master -> staging -> release. This means that you will always have to merge 'staging' into 'release' before merging 'master' into 'staging' since you don't want to override the middle branch before you get a chance to merge it
Now that we know the process(theory) let's see how we will actually handle it(the engineering part):
- Create a new branch. I named it 'merge-staging-release' and called it the intermediate branch as it merges 'staging' into 'release'. It should be created from 'release'!
- Merge 'staging' into 'merge-staging-release' by fully committing everything
- Create a pull request from 'merge-staging-release' into 'release' and commit with squash. You will have no conflicts as you've eliminated any possible ones at the previous step.
This three steps will give you a smooth merge of the two branches with a linear commit history because of the PR + commit with squash(you can usually do these by using GitHub but many other providers support it). Beware that without a PR, a merge commit will be created instead, which breaks the linear commit history.
Follow the above steps for merging 'master' into 'staging'.
Move of a single commit from one branch to a another
Same principles apply here as described above. Single difference being that instead of merging the whole branch, you cherry-pick the commit you want to move into the intermediate branch.
Notes
You will notice that the two branches 'release-candidate(staging)' and 'release' will appear as being behind 'master', that is absolutely correct and fine since we are always merging using a PR into them but never merging back. We don't need to merge back since the code is already in there.
What you could do from time to time in theory, is to delete 'staging' and 'release' at merge time and just branch them off master, targeting the right commit ofc(careful with the cherry-pick ones). I call this branching maintenance.