Reputation: 2295
We use TFS 2010 and have three branches: Dev -> QA -> Production.
In this particular example we decided to change the method parameter type and a name from "Guid reportGuid" to "int reportId". We did this change in the QA branch and checked it in. And now I'm trying to pull this change from QA to Dev branch. Usually it is done in the opposite direction but in this exceptional case we did what we did. Here is screenshot of merge tool. As you can see from the screenshot, the last check-in on the file in the Dev branch got change-set number 30282 and in the QA - 31002 (which is newer than 30282). As for me it's quite obvious that newer change should override an older one. But what TFS merge does is opposite. It applies old code from Dev branch (30282) over new code from QA branch (31002) and the result doesn't get the change.
Can somebody explain why TFS merge acts like that? Thanks in advance.
Upvotes: 2
Views: 3750
Reputation: 78643
You're posting a screenshot of the 3-way merge tool - and I suspect you're attributing to many smarts to it. TFS uses any 3-way merge tool for conflict resolution - by default, it includes the one pictured, however you can configure it to use any 3-way merge tool of your choice.
When a conflict is detected by TFS (in this case, a merge conflict, where the files were edited in both branches and then merged), it will attempt to automerge the contents of the files. If an automerge is impossible, it will require you to use the configured 3-way merge tool to resolve the conflict. TFS simply hands that tool 3 paths: "source" (the file in the branch that is the source of the merge), "target" (the file in the branch that is the target of the merge) and the "base" or common ancestor.
The common ancestor is the last version of the file that was merged between the two branches. If no merge has been performed, the common ancestor is the changeset that the file was branched at. This will remain the case until the first time you merge changes from the source to the target. For example, consider $/Main/A.txt
is branched to $/Branch/A.txt
at changeset 2. If an edit occurs on $/Main/A.txt
(as changeset 3), and an edit occurs on $/Branch/A.txt
(as changeset 4) then when you try to merge $/Branch
to $/Main
, you will have a merge conflict on A.txt
. The common ancestor in this case will be changeset 2 (the version that was branched.)
If you were to then resolve that conflict in your merge tool and check in the result (as changeset 5), then the next time you merge from $/Branch
to $/Main
, the common ancestor of A.txt
will be changeset 5. (Indeed, if you invoke "compare source to base" or "compare target to base" during TFS conflict resolution, you should be able to see the common ancestor as well as its version information.)
In any case, once the merge tool is invoked, it's ultimately the tool's responsibility to prompt you to deal with those changes. The workflow is tool-dependent, but a typical merge tool will compare the files line-by-line and will identify each line as one of the following:
If there exist no conflicting lines, then an "automerge" can be performed, meaning that the common ancestor is modified by taking the source-only lines from the source, the target-only lines from the target and the common lines from either file to produce the merge output. (TFS will offer this as the "automerge" option, if it's possible.)
Note that just because an automerge is possible (and typically works in practice) that it's exactly as naive as taking lines and no syntax checking is performed so it's possible that your automerged output is not really what you want.
Some 3-way merge tools may offer a mode in which they do a partial automerge - either by default upon opening or after some interaction - taking the common, source-only and target-only lines and then requiring you to resolve the conflicts manually.
The merge tool in your screen shot is the default tool bundled with Visual Studio ALM. The tool in TFS 2012 is significantly improved over that version. Regardless, you may have a better experience with a third-party merge tool.
Note that despite the labels, the merge tool doesn't actually have any idea which file is newer chronologically. (TFS provides the labels to the merge tool to provide you some context about those files, the merge tool just treats them as opaque strings.) Nor is "newer chronologically" necessarily the best merge strategy in all branching strategies. (I work on a team that uses a feature branch strategy - my feature branch has a relatively high velocity and I merge in changes from a main branch that takes well-tested changes from all the feature branches at a comparatively slower cadence. In this case, chronology is fairly unimportant and I need to merge my conflicts regardless.
Upvotes: 8
Reputation: 39
It seems TFS doesn't support indirect integrations, i.e. merging from one branch to another. You have to merge back to the parent, then merge to your other branch (DEV) See this post: http://social.msdn.microsoft.com/forums/en-US/tfsversioncontrol/thread/85c4ce74-59bc-4bec-a6e9-32b6e875a15a/
Upvotes: 3
Reputation: 6609
Looks like you've got a merge conflict on this screenshot right?
First, don't use the merge tool of visual studio/TFS, it's really not effective and not really intuitive. Use the free KDiff3 or Beyond Compare to get a better auto merge and a more user friendly interface.
Second, as far as I know there's no such thing as temporal coherence for merge in TFS (I may be wrong, but I've never heard about it). The two changeset you mentioned are not in the same branch so TFS doesn't care about which changeset happened after the other and what does it means.
Third, the direction of the merge doesn't change anything from branch1 to branch2 or branch2 to branch1. The only thing that changes is when both branches are directly related or not.
For me your issue is mainly a GUI based one, or maybe you used the auto-merge feature which is not smart at all in case of conflicts.
Upvotes: 3