1

It looks that eventually we moved our project to a bad branching strategy - "Cascading" (in question "TFS -- Sustainability of Cascading Branches" it was recognized viable actually). Now, after reading few articles and seeing it leads to infinite branching tree, I realized that it's bad and want to fix it. But it's not so easy as I expected. TFS allows merges only with parent branches (siblings merge isn't possible).

Here is the diagram of our current branches hierarchy: Current branching hierarchy

Looks weird, but it all started from small changes in latest release branch while trunk has been suspended in the middle of 3-month work. Then we made few internediate releases one based on previous one (up to 1.1.4). But when we started release 1.2.0, the story with trunk repeated and we must have suspend 1.2.0 and implement 1.1.5 hotfix.

Now I faced the need of merging 1.1.5 changes into 1.2.0 branch which isn't possible directly. I can only merge 1.1.5 with 1.1.4 which I wanted to avoid (who knows maybe we'll need to implement 1.1.6 based on 1.1.4 tomorrow). But it seems I have no other way out. Still it will be possible to create 1.1.6 branch from non-latest revision of 1.1.4.

Is it what I must do and isn't there a better way out?

And now comes big troubles and the main question. Eventually I'll need to merge all changes into trunk. And 1.1.5-1.2.0 problem is just a miniature copy of that. That's why I'm asking an optimal and least risky way to perform this merge.

My current plan is the following:

  1. Create branch "1.1.4 final" with the latest stable released version.
  2. Optional: Create similar final branches for all previous numbered releases. Should I do it? Most likely I won't need that versions in the future anymore.
  3. Merge 1.1.5 into 1.1.4
  4. Merge 1.1.4 into 1.2.0. There wasn't much changes in 1.1.5, so I shouldn't run into problems here.
  5. Merge 1.1.4 into 1.1.3, 1.1.2 and downto the release branch. Should I expect conflicts or problems here? I expect and hope not.
  6. Merge release into trunk. Most scary part =)
  7. Stabilize code in trunk.
  8. Now it is time to create a better branching strategy... I'm very unsure about this part at the moment.
  9. Create new "stable" (Main) branch from trunk
  10. Reparent trunk to become child of stable. This solution is suggested in related question "How to fix TFS incorrect branching"
  11. Should I remove current "release" and "R***" branches, or leave them as garbage?
  12. For next comming releases do not create separate branches - instead label the final revisions in stable branch. Actually "stable" branch will consist only of final release checkins.
  13. I'm NOT going to create the "integration" branch for QA of stable features - currently we all live in single active branch without problems.
  14. Create "alternate" branch based on stable for paralel development in case we'll need to once more suspend current work to make some urgent fix. Should I keep single alternate branch forever, or delete it once merged and create a new one (like R125) when again needed?

Planned branching fix strategy

The idea of this change is to have fixed limited number of branches (ideally 2, at most 3-4).

Please share your thoughts and concerns on my strategy, or propose a better one. I'm asking because not sure it all will work as I expect, don't know if it's the easiest way, and the mistake cost is huge.

Community
  • 1
  • 1
Sasha
  • 8,537
  • 4
  • 49
  • 76
  • Do you need to support old releases with hotfixes, or are the old branches essentially vestigial once the code is out the door? – Daniel Mann Aug 14 '14 at 20:01
  • @DanielMann, we never needed to produce hotfixes for older than previous release. I think that won't happen in the near future either. So branches R113, R112, "release" are gargabe now and present only for history. – Sasha Aug 15 '14 at 11:21
  • 2
    TFS supports "baseless" merges, which enables branches to be merged where there is no direct merge relationship. So you could merge your releases to trunk, and then start fresh with your new strategy. See http://msdn.microsoft.com/en-us/library/bd6dxhfy(v=vs.100).aspx and the /baseless option. – Polyfun Aug 20 '14 at 14:10

3 Answers3

1

Is it what I must do and isn't there a better way out?

I'd carefully perform a baseless merge of all the changes from the branches under release into trunk. I'd do this one branch at a time, and merge "All changes up to a specific version" and select all "Latest Version". That will give you a trunk that contains all of the changes from your releases.

Should I expect conflicts or problems here?

You may get conflicts, but with a bit of care and some forensic investigation of the history, you can get the changes into your trunk.

The normal process when working on release branches (even those not directly related to trunk) is to check into the release branch, then to RI (reverse integration) merge the change back to trunk. Some people prefer to check into trunk first and then merge into the release branch to avoid the situation where trunk may get forgotten about. It's six of one, half a dozen of the other IMO.

Should I remove current "release" and "R***" branches, or leave them as garbage?

I don't think it matters, you could move them into a folder called obsolete releases if you want to hide them, or just delete them - TFS deletes are soft.

Please share your thoughts and concerns on my strategy, or propose a better one

I wouldn't create a stable. Once I had everything in trunk I would be happy, the purpose of a trunk/Main branch is to be the stable releasable version of the code, if the developers cannot keep it that way (I'm not blaming them BTW), then working in feature branches and regularly FI merging into the feature branch is the best way.

Where you go next really depends on the process your company has for releases. One option is to "label" trunk when you have a release you would like.

Start -----L:R1-----C->

If you then need to put in a bug fix before release, you can branch from the label:

Start -----L:R1-----C->
           |    /
     B:R1  |--C/

Check the change into the R1 branch (B:R1) and merge it back to trunk.

This gives you a branch for releases if needed, but not too deep structure, you may end up with many branches, but you can use folders to keep them organised.

I hope this helps, in closing make sure you read the ALM Rangers branching guide - it covers the main TFVC branching strategies you are likely to need and when you should use them.

And finally, my question to anyone who wants to make a branch is "How will you release this code?", this helps me make branches to solve problems, instead of creating problems. If I don't know how the code will be released, I don't know the best way to structure the branches - I was once involved in a project with a hierarchy of 23 branches off Main, that all ended up coming together before been tested or released - we could have used one :).

Last thing, if you have a VSOnline account or another Team Project Collection, you could try re-creating a simpler version of your problem and experimenting with solutions.

DaveShaw
  • 52,123
  • 16
  • 112
  • 141
  • Thanks for the answers. It looks good enough to implement. Also recreating and testing strategy a sandbox is a must-have step. I'm going on vacation in 30 min, so will check your answer in 2 weeks to finally review, test and accept it. – Sasha Aug 22 '14 at 12:42
  • Good luck and enjoy your Holiday - please don't think about branching for 2 weeks :) – DaveShaw Aug 22 '14 at 13:03
  • 1
    Very good synthesis --- "How will you release this code?", this helps me make branches to solve problems, instead of creating problems. If I don't know how the code will be released, I don't know the best way to structure the branches. --- – Giulio Vian Aug 24 '14 at 13:13
0

Your merge stratigics looks ok to me but i will try to finish with three branches diagram.

We are using three branches Dev,Test,Release.

most of the builds are from dev and are labeled. (same as trunk at your diagram). Then we move it to qa and continue development. If there is an issue \bug and Dev branch is in future development we set test branch to the label and fix the issue on test branch and merge it to dev and again and take label. If we have an issue with production we use the label on release branch fix the issue, label it and ofcourse merge it to dev. This how it all done using three branches.

Ofcourse you can always use feature branches for long and defacult features.

Erez H
  • 88
  • 1
  • 13
0

Finally, I preformed that merge! Thanks @DaveShaw for recommendations, I mostly used them. But want to publicate my invention which I believe significantly saved time.

Instead of performing a baseless merge from R120 directly into trunk, I created an internediate branch dev, from the common root revision of R120 and trunk and preformed a baseless merge from R120 into dev. That generated more than 600 files with conflicts! But it was easy to resolve them - Take everything from the R120.

Then, since branches dev and trunk have common root, I could merge them with regular merge (not baseless). That performed much-much better than a baseless one and generated only 11 files with conflicts and I could resolve them in only 1 day - all those were real conflicts needing manual resolution and code editing to merge. So that saved me time to distinguish real 11 conflicting files from 600 those which are not a real conflicts and can be resolved automatically.

Next, I will stabilize both branches and switch their roles (it appeared that currently dev plays role of main (stable) and trunk is broken). So I decided to use branching strategy "Development isolation" which will evolve soon to "Development, Feature and Release isolation".

For most of my remaining questions, @DaveShaw provided good explanative answers I have nothing to add to.

Sasha
  • 8,537
  • 4
  • 49
  • 76