Reputation: 631
On our TFS server we have a branch structure like this
9
8.3
8.2
8.1
8.0
Where each branch is a child of the branch above it, so that it's easy for developers to merge changes they make to all subsequent versions (e.g. changes in 8.2 up to 8.3 and 9). I now need to add a branch for 8.4 and here is where my problem is occurring. I can't find a way to add an 8.4 branch that is a child of 9 and a parent of 8.3. It must be created in such a way that when developers try to merge from it, 9 and 8.3 show up in the drop list as possible targets.
I had thought i could just create a new branch off of 8.0, the force merge each branch down one level and rename them, so that the existing 8.0 would become the new 8.1 etc, then the existing 8.3 would become 8.4 and everything would be fine. However it's proved impossible to merge a branch completely (it doesn't remove files that exist in the target but not the source for example).
Is there any way to do this? I can't use a baseless merge because i can't lose the ability to to a UI merge in the future.
Upvotes: 1
Views: 3195
Reputation: 20782
I'm not sure how you even get into a situation like the one you describe. How were 8.1-8.3 created? How do you plan to handle 9.1 (or 10)?
"Star" configurations are more common:
- 9 - 9.0
D \ / 8.3
E - QA / 8.2
V / \ - 8 - 8.1
\ 8.0
You may have to make one or two more total merges per fix, but overall it's much more flexible.
The workaround you came up with via Rename is a good one. I can't think of anything better based on the existing structure.
* answers to questions *
From what I see here 8 and 9 aren’t really working branches and would never be released, is that correct?
Yes.
Since 8.0 isn’t a child of 8.1 how do you get your changes to 8.0 into 8.1. It appears that to get changes from 8.0 to 8.1 you’d have to merge them into 8 then back into 8.1. But if that’s correct then you would also have to merge 8.2 changes into 8 to get them to 8.3. If that’s the case then what prevents 8.2 changes from accidentally getting copied into 8.1?
You're right, this wouldn't work. I made the assumption that only one minor version of each major version was maintained. If you were to draw the "star" in a more generalized way, the intermediate release branches (8 & 9 in my example) represent isolation. There should be no parallel changes happening inside their scope. If major version # isn't enough to separate active from inactive branches then you'll need different criteria to apply this idea.
Also we are currently working on 8.2, 8.3, 8.4 and 9 all concurrently. I don’t see any merge path from any version of 8 to any version of 9. Is it not possible to merge from 8 to 9? Also, what do the QA and development branches contain? It would appear they can only have the latest version, so in this picture they would be the same as 9?
I usually think of things working the other way around. The vast majority of changes are made directly in Dev branches, then slowly pushed to integration/QA/UAT/Release environments with progressively more stringent quality standards. In my diagram this flow is left-to-right. Occasionally you may need to fix something directly in right-side branch, eg if a customer finds a high priority issue in something already released, but that's the exception and must be treated with deserving caution. On the bright side, if this happens then merging right-to-left can (& should) proceed optimistically, i.e. early & often.
If you can identify ahead of time which changes are going into which releases, segregate Dev branches accordingly. In other words, if you have work you know won't be done until 9.x, put it in a different branch from any Dev branches with 8.x features. That way the latter can safely do a complete "copy-merge" (no cherry picking) as their work flows rightward, ensuring QA isn't wasted on code that hasn't undergone integration with parallel branches (or decoupling from accidental 9.x dependencies) yet.
The rightmost branches, where actual releases are represented, don't even need to be created until the code has diverged irrevocably. Branching for release is basically a signal that development is shutting down and vNext is officially underway. From an SCM perspective, it sets up a one-way barrier in the flow of changes to ensure that old code doesn't acquire new dependencies (as in your question about getting 8.2 changes mixed into 8.1).
Let's look at the overall sequence I had in mind when I drew the diagram. For the sake of reuse the drawing above, I'll hang onto my assumption you only maintain one 8.x and one 9.x release at a time.
That's obviously not the exact pattern for you. In order to accommodate three 8.x versions under concurrent development, you need to base the decision in step #5 on something other than just version number. I don't know enough about your business to tell you what that should be.
In addition, you may not be able to separate 8.x feature development from 9.x feature development so easily. Plans change. If a 9.x feature gets moved up to 8.x, you'll probably need to cherry-pick from its Dev branch. If an 8.x feature gets punted to 9.x before the "8" branch is created, you have some hard work in your future -- no branch structure will solve that.
Similarly, steps #5-6 depend on things finishing in sequence. It works best when 8.x reaches the "almost done" state (as represented by the RHS of the tree) around the same time that 9.x branches need to start sharing their work with each other and with QA. Again, reality often dictates otherwise. For some the solution is trivial: 9.x teams can promote & accept code without affecting the main trunk by creating a level of indirection. (On the chart this would be branch sitting just to the left of "QA" that's a common parent of some of the Dev branches.)
But if I understand your situation, feature development might be split into 4 or more future release milestones. Unless your code is extremely modular AND you are very comfortable with cherry-pick merging, you might want a "bushier" branch tree. Imagine if "8" and "9" above had their own independent array of Dev/QA branches feeding them. Or for all I know, every minor version will need its own miniature Dev-QA-Release promotion model inside its piece of the tree. Depends on how you end up segmenting active release areas from each other. In any case, having multiple effective "trunks" removes the potential scheduling conflict over use of the QA branch, at the cost of (a) more steps to propagate 8.x changes up to the 9.x section of the tree (b) sheer complexity. I'm not a fan of this approach and hope you can avoid it.
Ok, enough for today. Further reading:
Intro to the standard Dev-QA-Release model I've been more or less assuming all along:
Presentation on why you want to arrange your branches so that code generally flows from an unstable "side" of the tree to the stable "side" (in her PDF slide notes it's up/down instead of left/right); why the rules for merging in each direction are very different
Whitepapers supporting the idea that keeping a single mainline (like "QA" in my diagram) is better than letting release branches cascade off of each other.
Upvotes: 4
Reputation: 631
OK I've figured out a workable solution. I'll put it here in case anyone else faces a similar situation (assuming anyone could even understand the question). I will simply branch from 8.3, then rename the newly created branch to 8.3 and rename the old 8.3 to 8.4. This will give a situation where changes 8.4 can merge to 8.2 and 9, and 8.3 can merge to 8.4. The only issue will be that 8.2 can't merge directly to 8.3 anymore, but we probably won't have any more work done in 8.2 so that shouldn't be a problem. If we do need to make another change in 8.2 we can get those to 8.3 by going through 8,4 (but we will have to be careful not to get any 8.4 changes into 8.3 when we do it)
If anyone still wants to comment or make suggestions it will be welcome. Thanks
Upvotes: 1