Monday, April 16, 2012

Merging to Grandparent in TFS2010

I am not a Team Foundation Server (TFS) expert, so I was unpleasantly surprised when I discovered an apparent limitation within it the other day. From what I can see, the TFS merging dialog allows merging changes back to the closest ancestor (parent branch) only. Why is this a problem? Consider the following scenario:
  • Main development happens in the master branch (let's call it "master") 
  • One feature is developed in a "feature" branch which was started from the master some time ago 
  • A small feature bug fix was done in yet another branch "featureSP" which was started from the "feature" branch 
When you try to merge the "featureSP" branch, the dialog will show only one choice for the target: "feature" branch, the parent. This limitation to 3-way merges looks strange.

For a 3-way merge to happen, three check-ins should be sufficient: base, source, and target (source and target should be traceable to base check-in; http://en.wikipedia.org/wiki/Merge_(revision_control)). Source check-in (in our scenario, source it’s "featureSP"—the latest check-in) is traceable to base though both branching operations, so all information is available. I guess this use case has never been considered valuable. I suspect merging changes between sibling branches in TFS may be prone to the same problem, but I haven't tried it yet.

Daniel Sniderman suggested a workaround to this problem by using a baseless merge (from command line with /baseless parameter; see MSDN), thus forcing TFS to use a 2-way merge instead of a 3-way. However, the 2-way merge usually produces a worse result by leaving more unresolvable conflicts. A baseless merge of "featureSP" into "master" would establish a relationship between branches, making future merges easier (from the dialog). I suspect that once the new relationship is established, the old one is lost and merging from "feature" to "master" will bring the same problem again, but I haven’t tried this approach yet.

Other TFS limitations similar to the one described above make branching in TFS a strategic operation that requires planning and coordination. In contrast, Distributed Version Control System (DVCS) keeps branching tactical (even local) and much easier to use; the branch is just a pointer to the commit in the version graph (at least in case of Git). Branches can be created and removed while keeping the version graph the same. Merging in DVCS uses the version graph and does not limit the number of branch pointers between source and base commits.

For a nice comparison of merge algorithms in systems with and without merge metadata (Git and SVN), see Stackoverflow. TFS keeps information about branches and merges (check operation types in Change Details window), so it should merge efficiently.

No comments:

Post a Comment