Option A. Just using mainline and tagging for release
Pros:
-
You avoid merge hell.
-
Keeping to the mainline encourages some best practices like proper release planning, not introducing a lot of WIP, using branching by abstraction to deal with out-of-band long term work, and using the open closed system and configurable features for dealing with managing works in progress that may; or may not; need to be disabled now or in the future in order to release or to avoid a full rollback.
Cons:
-
Dealing with works in progress becomes an issue and adds to potential surface attack area when it comes time to release.
However, if your developers are disciplined then new features should be configurable and modular and therefore easily disabled/enabled, or there is no WIP and at each release point all work is either completed or has not yet been started (i.e. Scrum).
- Large scale/out-of-band changes require more thinking ahead of time to implement (e.g. branching by abstraction).
Personally I prefer this approach. Code coverage and unit tests should identify code that isn't ready to go out the door and people should not be working on code that will not be released during the current iteration. Branching by abstraction or other mechanisms can be used to deal with long term changes and works in progress.
When you don’t do this you start finding yourself dealing with merge issues, stale code, features that never get released, etc.
Option B. Branch by release
Pros:
- You can begin working on the next iteration while the current iteration finishes its round of acceptance testing.
- Other stuff im sure.
Cons:
-
- Tons of branches.
- Still need to tag branches at release points.
- Still need to deal with WIP and merge WIP from previous release branch into next release branch if it's not going to make it and still need to disable or yank it of release branch and re-run acceptance tests
- Hot fixes need to be applied to more branches (release branch + hotfix + new tag + merge hotfix into vnext branch and possibly vnextnext depending on where the hotfix falls.)
I'm not a huge fan of this solution ^_^.
Generally I would recommend just trying to stick to the mainline. If your developers are having trouble with not writing WIP that can be easily yanked when it fails the cut or that is checked in early for the next release then you can start talking about tagging the code at the point where it should be code complete and branching from there if necessary to address overlooked defects and bugs that your developers unit tests failed to catch.
Ideally though I think you want that to be the exception process, not the rule.
Option C. Crazy Bonus Option
If you want to get fancy you can also consider a per-user-story/per-feature branching model. (A terrible idea in TFS or any non DVCS while at the same time incredibly trivial to implement if using a DVCS like git or mercurial).
In the past I implemented the below for a previous employers maintenance team which worked with a legacy code base that could not easily be ported over to mercurial from svn. A lot of unnecessary work was involved to meet a business requirement of a always releasable mainline rather than just coordinating releases better but . . .
- Features were developed by devs in their teams dev branch.
- When a feature is ready to be peer reviewed the devs bundle it together into a single merge from the Dev branch into the CR branch and include the feature id/user story in the title. *Enforced by pre-commit hook*
- After it passes CR an admin tool is used to Promote the feature into the QA branch. (I wrote a little terminal application that listed the user stories present in the various acceptance stages and allowed the operator to promote or demote it inbetween those acceptance stages)
- QA runs automation and manual usability tests. If the feature is good its pushed into the release branch (mainline). If the feature is rejected its demoted/reverted out of the QA branch until devs can address the issues brought up during test and add submit a patch to the CR branch.
- If code was reverted from the QA branch and a fix is applied the terminal tool will re-apply the necessary changes to bring the feature back onto the QA branch from the CR branch so that QA may re-review the code and either promote it or demote it again.
- At any point in time the release branch should be in a stable releasable state.
- After a release new Dev, QA, and CR are spun from mainline.
Your branching strategy looks really good to me. I have done the same strategy in the past and it works fine. Draw it up on a whiteboard and get all your devs to understand it so that people do the right work in the right branch. Teach and explain to everyone the switch command and get everyone to doublecheck the branch that they are working on. (Or alternatively just check out the entire repo... depending on your code size :) Remember... svn revert is your best friend!
Personally I prefer one person to be the "merge/branch" person (with a few backup people as reserves) to ensure that everything is kept under control and consistent. Let that person become your SVN guru and you'll be away.
A few other helpful hints:
- Encourage frequent SVN updates and SVN commits. Every day is preferable.
- Cross branch merges should also be done every day, or alternatively whenever a bug is fixed. Do them early and do them often! (you'll get good at it real quick).
- Get a good diff tool - beyondcompare is ace. The standard tortoiseSVN one... not too good.
- Don't check in stuff that changes upon compilation (like your output directory)
- Try to clean up your repo before you start branching (get rid of files that don't need to be under version control - things like external libraries etc). The smaller your repo, the better
- Changes to your Production branch and QA branches should be as small and short as possible - don't start refactoring code there, just fix the bug.
- Make sure you branch from the top level of your solution - and if you have a DB I hope you've scripted all of your DB stuff (like stored procs or triggers)
Also tell people not to move folders around unless it's strictly necessary. This will make your merging much easier :) (Don't do what I did, launch upon a massive directory restructure halfway through a huge change to trunk which screwed up all of our merges... I was pretty popular after that).
Best Answer
If it concerns a feature that will be delivered to all customers once it has been fully tested, and this one customer takes up part of the testing effort, then it is best to use a second release branch for the testing of this feature. After the feature has been found to be stable enough, the second release branch can be merged into the official release branch.
If the feature will not be used by all customers, then it is better to use a feature toggle, as outlined in the answer by @aquaranga.