Branching is a tool. It's a good tool. It's just overloaded. Developers and CM managers use branching for long term parallel development; for short term parallel development; to collect files into a change (a.k.a. labeled branch) or into a feature (a.k.a. labeled branch); to promote files to the next level, from which they are promoted to the next level, and so on; to collect files for a release or to collect an incremental release; to check in code that would otherwise have to sit on their hard drives because they don't want to break the build.
This is too much. If I've got branches of all types, I've got merges of all types, and I've also got labels of all types. There are baseline labels, release labels, change and feature/fix labels, promotion level labels, and so forth. Some can be applied multiply to the same file, some are one of, others need a whole set of files before they can make sense.
Enter the branching strategy document. It helps make sense out of labels. It helps make sense out of branching. It tells me what happens when a new release stream is to be opened up. I can use it to implement triggers to help support and enforce the strategy. The problem is, it takes too long to put together and review, unless your team has been through this a number of times already. And it's too complex, not for developers to understand, but for developers to use their precious time trying to read/review, understand and apply it, when there are other, more urgent things to do. And then it the strategy changes to deal with the unforeseen. It should all just be intuitive. But then, how would you ever design the right configuration specification? You could borrow it from your peer, I suppose.
There is a better way. It requires understanding and modeling the process better. Don't use branches for everything.
More Branches, Less Branching?
Let's start out by saying you can actually reduce branching and merging by using more branches. I know that sounds contradictory. What I'm referring to is the main branch strategy. Many will advocate keeping a single main branch always. Then most development is done on the same branch, main. That sounds easy. I don't agree, at least in most cases. I prefer the step model, where each major release development stream has its own main branch. So instead of one main branch, you have a rel-1 branch, a rel-2 branch, and so forth. Maybe you introduce a rel-1.5 branch at a later point.
Some say, this is not really different. Instead of starting a rel-2 branch and continuing support on the rel-1 branch, you transition the main to handle "rel-2" and create a new branch for "rel-1" support, if and when necessary. Then your developers just continue to work on "main." When it comes down to it, each feature implementation or problem/issue/defect fix has to be targeted to a given release (stream), and possibly more than one. Rather than implementing release 1 changes on a release 1 branch, release 2 changes on a release 2 branch, and so forth, you look at the state of main and decide where to make the change. So for a release 2 change, if main is still tracking release 1, you need to use a release 2 branch. That branch is then merged into the "main" when it starts tracking release 2. When main starts tracking release 3, you're back to using a release 2 branch again. On top