A common release branching strategy looks like this:
The idea is that when you have a conflict between work required for the current release and work for the next release, you create a release branch. Whatever the timing of the branch creation is, there is a temptation to create a new branch for every release.
There are some trade-offs in doing this:
- You do know where you're at, so that's good;
- If you need to support many older releases at the same time, it is easy to out the right place to patch;
- You need to track what the "current" branch is, especially if you wish to use automated deploys;
- You need to actively verify whether the merges back into your mainline have been performed.
- You could, in theory, work on stabilizing multiple releases concurrently.
Instead, I advocate for role based branching. We observe that the release branches really serve two roles: stabilization and patching. So instead of performing these activities on the same branch, we copy (promote) the code from one branch to the next until we end up in the production (or hotfix) branch, where patches can be applied:
The tradeoffs here are different:
- You can only work on one stabilization at a time ;
- Patching the latest release is easy, but patching older releases is more complicated, as you need to create an ad-hoc branch at that release, patch there, then merge through;
- You always know where your current release branch and your current patch (hotfix) branch is;
- Configuring automated deploys to test environments is easy, as the source locations are constant;
- If the merge through steps have been omitted, you find out when you try to promote, as this merge will no longer be a copy merge.
- The total number of branches known to your version control system is reduced.
- Use branches to reflect the role or the state of the code contained in the branch;
- Use labels to reflect versions;
- Merge stable code into unstable code and resolve in the unstable branches;
- Ensure that promotions are true copy merges.