0

So, I've been scratching my head for a couple of days trying to come up with an efficient way to manage Releases/Iterations with TFS branches.

Here's the situation:

We have a project for which we have releases, and for each release we have iterations. Releases are the new versions that we put into production and iterations are just development phases that need to be tested in QA.

Iterations are a bit like features. Let's say you want to develop a web site to show items (iteration 1), and then sell them (iteration 2) and package it all in the first release. For the QA fix, it is done in the iteration branch and merged in QA. Since we don't commit in QA there's no conflict to resolve when we merge.

So the workflow looks like this (a lot of parallel work needs to be done because of the tight schedule):

  • For Release 1
    1. Start the development of Iteration 1
    2. Start the development of Iteration 2
    3. Iteration 1 goes into QA
    4. Start the development of Iteration 3
    5. Iteration 1 QA is done
    6. Iteration 2 goes into QA
  • Release 2 starts...

In resume, lots of parallel development, one iteration in QA at a time, when all the release's iteration went through QA it goes to production.

So we need to come up with a branching solution that allows to easily merge between development branches, and then go into a QA branch. So far, we came up with this branch structure

- Main
   |- QA_Release_1
   |  |- DEV_Iteration_1
   |     |- DEV_Iteration_2
   |        |- DEV_Iteration_3
   |- QA_Release_2
      |- ...

With this, we can easily merge between dev branches. But at some point when iteration 1 QA comes to an end, we disable the branch (either by deleting it, or deny acces to check out/in). When that time come, the strategy is to reparent the DEV_Iteration_2 to QA_Release_1.

For this to be done, we need to make a baseless merge, which creates a lot of conflicts. And if I understand correctly, a baseless merge is just a folder compare, without taking into account the change set merges that happened before.

So I guess the first question would be how much merge trouble (if any) are we getting ourselves into by doing this? Is it OK to just ignore the enormous merge and just fix the tons of conflicts when reparenting?

Second would be: is there any more efficient way to achieve that goal?

Edit: I miss git...

We continued searching for a solution, and a coworker sent me this link:

Gitflow Workflow

Which is, if you take out what's directly related to git, exactly what we need to do. It would probably look like this in TFS:

- Main
   |- Develop
      |- QA_Release_1
      |- DEV_Iteration_1
      |- DEV_Iteration_2
      |- QA_Release_2

Problem is, TFS doesn't like skipping branches. As soon as you don't merge in the parent or a child, it's considered as a baseless merge. So since the QA_Release_1 is created under Develop, it won't easily merge into the Main. This brings me back to my first question: are baseless merge a trap?

PhilDulac
  • 1,305
  • 20
  • 32
  • I was trying to post an answer but the I realized I need more information for this. Why do you actually need the DEV_Iteration_x branches? What use do they have? And what happens if the stuf you 'released' to QA produces a defect or other imperfection? Will you solve it in the current iteration and push it back to QA with the QA 'release' of iteration 2? In general each merge conflict is a potential defect, so prevent them as best you can. [Have a look at this as well](https://www.visualstudio.com/en-us/articles/branching-strategies-with-tfvc) – Sander Aernouts Jun 21 '16 at 17:42
  • I updated the question to include more details! – PhilDulac Jun 21 '16 at 19:58

1 Answers1

0

On my job I use the following model:

Branches:

  1. Trunk/Main branch
    • build and automated tests are OK
    • no unfinished work (if a change needs several commits, use feature branch)
    • ready to become a release candidate (if a change introduces any blocker, it's not committed here)
  2. Feature branch

    • created if a feature or a fix needs more than one commit
    • a branch for a specific feature or a bug fix
    • everything is allowed: broken build, failing tests
    • eventually is merged to trunk
    • occasionally trunk is merged to it (to reduce deviation between branches)

    • before merge to the trunk everything should be cleaned

  3. Stabilization branch
    • created for every version to be supported
    • matches some revision of the trunk + merges of some changes later + workarounds
    • builds for manual testing are created from here

Workflows:

  1. Small feature/fix:
    • just commit to trunk
  2. Big feature/fix:
    • create feature branch
    • make many commits there
    • merge to the trunk
    • delete the feature branch
  3. Fix for a bug found by manual testing:
    • fix in the trunk (by #1 or #2)
    • merge to the stabilization branch
  4. Workaround (quick and dirty fix which we will clean later):
    • fix directly in the stabilization branch
    • do not merge to the trunk

I used it on SVN and TFS and it doesn't seems to create problems. Since all branches are made from the trunk TFS should have no problems with merge.

maxim1000
  • 6,297
  • 1
  • 23
  • 19
  • If you have to develop 2 features, and the second one depends on the first one, how do you merge the code from feature one to feature 2? If you create feature 2 from feature one, you'll have to do one of the following once feature on is done: keep feature 1 branch alive to merge feature 2 into it an then merge into the trunk, or do a baseless merge to merge directly into the trunk. If you create feature 2 from the trunk, you'll have to wait until feature 1 is in the trunk or do a baseless merge between feature 1 and feature 2. I don't think it solves my problem. Thanks for sharing though! :) – PhilDulac Jun 22 '16 at 15:04
  • If Feature 2 depends on Feature 1, and feature 1 is still in development, then Feature 2 should be branched from Feature 1. All development of Feature 2 is done in Feature 2. All onwards development, not affecting Feature 2 of Feature 1 is done in Feature 1. If you decide only to release Feature 1, then Feature 1 branch is merged back into trunk. Likewise, if you wish to merge both, then both branches are merged into trunk. Alternatively, if no onwards development is required in Feature 1, then Feature 2 is merged into trunk. – ManxJason Jun 22 '16 at 15:44
  • Yeah, but to merge Feature 2 into the trunk, you need to do a baseless merge, because Feature 2 was created from Feature 1. Will this cause future merge problems? I just don't know what happens to the files history when a baseless merge is done, how it will react when were going to do basic merge. – PhilDulac Jun 22 '16 at 17:44
  • @PhilDulac, I will merge feature1 to the trunk and then from the trunk to the branch for feature2. Normally this need to wait is not restrictive to me because I try to reduce dependency between features. And if they are really dependent, then I prefer to base feature2 development on a stable code which is trunk, not some intermediate state which is on another feature branch. – maxim1000 Jun 22 '16 at 17:58
  • @PhilDulac When you merge, you're merging the commit history. You wouldn't experience any merging issues in the future, other than standard conflicts – ManxJason Jun 23 '16 at 18:35