Looking for a TFS branching scheme that supports an integrated testing branch
We are considering moving from SVN to TFS, so I am trying to find a proper workflow to follow in TFS to accommodate our needs. There are a lot of branching scheme discussions out there, but most that I have seen have 1 thing in common that doesn't fit our needs; almost all branching schemes assume your branches are testable.
So we create some feature branches from Trunk:
Trunk --(branch)--> Feature1
Trunk --(branch)--> Feature2
Trunk --(branch)--> Feature3
In our case, we are making 'feature' branches, each feature branch can be unit tested, but can not be QA tested. This is because each feature branch would need to have its own DB instance, and a web server, and we plain don't have the resources for that. So we merge our feature branches back to a 'testing' branch. Our QA team then tests all the features (as they are ready) in the testing branch.
Feature1 --(merge)--> Testing
Feature2 --(merge)--> Testing
Feature3 --(merge)--> Testing
Now this is where things get strange... Note that the feature branches are not really int he same hierarchy as 'testing' branch. In SVN I guess you would call this a 'baseless' merge, which I don't think TFS supports...
In QA testing, a particular feature can fail testing, or more commonly the business will decide "nevermind, we don't want Feature2 to go out this release, we'll wait until next release".
At some point, when a feature has passed QA and the business signs off on it, we merge our accepted features to Trunk (release/production).
Feature1 --(merge)--> Trunk
Feature3 --(merge)--> Trunk
Then we build our release off of Trunk (and tag it with a version number)
So what I am looking for is a way to make something similar work in TFS. Since you seem to only be able to merge to an ancestor, I could possibly set this up like:
Trunk
|- Testing
|- Feature1
|- Feature2
|- Feature3
And merge fr开发者_如何学Com the feature branches to Testing. However, then I would need to only merge the revisions that originated from Feature1 and Feature3 from Testing to Trunk, ignoring Feature2's revisions. This seems like it would be a terribly tedious error-prone job of hand-inspecting each change to see what branch it came from? This is why in our SVN scheme, we would have merged our feature branch directly back to trunk.
It seems like having feature branches that have to be re-integrated to a common testing branch should be fairly common, but I guess I'm not seeing an easy way to only get the changesets that originated in a particular leaf for the next step of the merge.
Anyone have any input? We are certainly open to revising our branching scheme too. What we did before just happen to work OK in SVN. I suspect it wouldn't be hard in git either, since you could actually squash an entire feature into a single commit, and just merge that commit to any other branch.
Thanks for any input!
Other notes:
We are using TFS 2010. I forgot to mention that earlier.
Another option would be removing all the changes from a feature from the Testing branch, before merging it to Trunk. This would be a 'reverse merge' in SVN. I've seen that there is a tf.exe /rollback
command, but it looks like it takes a changeset number. Each feature might be multiple changesets, so I still don't see a way to figure out the list of changesets in Testing that originated from a merge from FeatureX...
Baseless merges are supported in TFS, they are just to be made via command line. See here for an intro on how it works. Once you 've done a baseless merge, an additional 'link' between the branches is established & from then you 'll be able to merge from the GUI.
So your proposed structure could work:
Trunk
|- Testing
|- Feature1
|- Feature2
|- Feature3
provided you have done three baseless merges (Feature1 -> Trunk), (Feature2 -> Trunk) & (Feature3 -> Trunk).
Another similar -yet possibly a bit better- approach can be the following:
Trunk
|- Feature1
|- Feature2
|- Feature3
|- Testing
and then -by hand- establishing via baseless merges (Feature1 -> Testing) & (Feature2 -> Testing).
This way you 'll be able to use Testing
as a dump-zone, and once everything checks out ok for FeatureX in Testing
(tests ok, mgmnt decides to use it) you 'll be able to push it to your trunk.
In general, baseless merging is not considered 'best practices' by the ALM rangers guide on TFS branching. Looking at you workflow, I 'm afraid I can't find ATM an alternative for you that doesn't use it.
There are definitely tradeoffs to both and, in my opinion, it boils down to how much overlap your feature crews have with each other. As pantelif noted, you can indeed do baseless merges in TFS too, but it's less glamorous than when you have a proper merge relationship between branches and you lose a lot of the merging capabilities when you do a baseless merge.
I think identifying the changesets to merge in your second illustration:
Trunk
|- Testing
|- Feature1
|- Feature2
|- Feature3
is less tedious than you think. Consider that when you merge several changesets (say 1, 2 and 3) from Feature 1 into Testing, this merge will get committed as a single changeset in the Testing branch (say changeset 4). When you've signed off on the feature work, you can merge up to Trunk just by merging with Selected Changesets and choosing changeset 4. (That is to say that you don't have to reselect all those original changesets 1, 2 and 3.) You will, of course, have to do a little work to determine which merge changeset contains that feature work, but I'm assuming that you're not merging into trunk so frequently that it would be hard to identify. (And if this is a bad assumption, then ignore me.)
But the big problem with this structure is when there's merging required between Feature 1 work and Feature 2 work. Let's say they both make changes to the same classes. Now if you only want to promote one of the feature branches up to Trunk then you'll have to unmerge those changes until the other feature's work is ready to be promoted. And that does sound tedious and error prone.
If this is a total edge case and your feature branches work mostly independently with little overlap and trivial merges, I'd choose this structure. If, however, this is a common scenario, then I'd probably go with the baseless merge route.
So I think as people mentioned rightly above, baseless merge from command line would help you out. Secondly, you mentioned about 80 commits. In our project we create tasks in TFS. As per process, each developer is able to commit only if he first "associates" his check-in against a task. So If i have a fix x, I create a task for the same, and then even if there are 80 commits, all of them are linked to this task, which allows me to easily view the grouping anytime in future.
精彩评论