Question

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.

Was it helpful?

Solution

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.

  • Easy to create new release branches at the correct place in the hierarchy.
  • Easy to define and enforce rules on code flow. (in this diagram the cliche becomes "merge left, copy right")
  • Still relatively easy to ensure changes make it everywhere they need to.

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.

  1. Create Dev/QA branches off the trunk (exact details vary with team size & dependencies)
  2. Lots of work happens in Dev branches
  3. Branches containing 8.x work start to push rightward as features come online and quality standards are met
  4. All branches (including ones with 9.x-only features) accept changes from their parent branch early & often -- in the diagram QA is everyone's parent, but same holds if there's another layer of indirection in there
  5. After the last 8.x feature has made it into QA and passed its requirements, the "8" branch is created
  6. Now it's safe for 9.x Dev branches to start pushing code to QA without worrying about those changes getting comingled into an 8.x release. Future merges with 8 (and any children) are right-to-left only.
  7. 9.x code flows in & out of QA just as 8.x did: cautious rightward copies, eager leftward merges.
  8. 10.x Dev branches may be created if desired.
  9. Meanwhile, version 8 is in final bugfix mode. Once v8.0 is completely finished, the 8.0 branch is created. Same rule: only right to left merges allowed.
  10. As customers find bugs in 8.0, they may be fixed in a few ways.
    • Directly in 8.0 branch, then merged to 8 and back around the tree. This is the least error prone, but may be annoying as developers context-switch between 8.0 work and vNext.
    • In 8, QA, or even one of the (now exclusively 9.x/10.x) Dev branches. Then merged via carefully cherry-picking just the desired changeset back around the tree, or via a baseless merge. This is more likely to fit into the day to day workflow for developers primarily focused on future releases, but carries some risk (and thus higher testing cost).
    • Directly in 8.0 and again in Dev; TFS does not participate in any merging. This is generally easiest when the change is small and/or the codebases have diverged to the point where it would take longer to piece together the diffs than to make 2 independent fixes by hand.
  11. When you've collected enough fixes to justify a minor release, create the 8.1 branch. Now 8.0 is completely read-only, 8.1 is subject to the same rules 8.0 previously was, and 8 becomes a collection point for potential 8.2 fixes.
  12. Back on the development side of the tree, the last 9.x fix successfully passes thru QA. You create the "9" branch, paving the path for 10.x development.

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.

OTHER TIPS

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top