Hi everyone:
I have the following branching scenario:
BranchA - Version 1.0 of the product, currently in production, currently being maintained
- Branch B - Version 1.1 of the product, currently under development (child of BranchA)
Obviously, bug fixes in branch A need to be forward integrated into branch B. This works, but the scenario below is confusing, and can potentially cause devs to merge incorrectly:
-
Branch V 1.0 into V 1.1
-
Make changes to code in V 1.1; file class1.cs
Check in changes -
Make changes to code in V 1.0 (e.g. bug fix); file class1.cs
Check in changes -
Merge V 1.0 to V 1.1; latest version
Conflict window pops up => understandable, both versions of class1.cs have changed
Merge the files
Accept the result
Check in the merge to the V 1.1 branch -
Make more changes in V 1.0 (however, no additional changes in V1.1)
Check in changes -
Merge again
=> Conflict window appears again...
I find it confusing that the conflict window appears again in step 6. The file of V 1.1 hasn't changed, so there shouldn't be any conflicts. (There aren't any; or at least not any that haven't been resolved upon the first merge)
It's not just annoying, but it could cause devs to get really confused and merge incorrectly. As time goes by, the number of changes in both files could be considerable. Devs will have to remember which changes are the ones that need to be preserved.
I am not sure if I am doing something wrong, but I feel that VSTS should only merge those changes of V 1.0 into V 1.1 that occurred since V 1.0 was last merged into V 1.1; not since the branch was created.
Any help is appreciated,
SA.

Forward integrating (parent-to-child) bug fixes always causes conflicts
detzX
Agreed. Actually, the fact that it's a 2-step process is the reason why we can't distinguish "edits made by merging file contents" from regular edits to B. Between pending the integration and submitting the checkin, the job of merging contents lies with the client: from the server's perspective, "anything" could happen (i.e. you can upload any arbitrary file as the new/merged version).
Unlike regular edits to B, the server does give B credit for all the changes in A up to that point. What it can't do is give A credit for the merged version. You'd see this if you tried a reverse integration: it would try to bring over the merged version, just as if you'd created it via a regular edit in B.
But still there is a window that lists the file as having a "conflict"...
I see what you mean. I believe this is merely a terminology issue. "Conflict" is an overloaded term between what I call "tree conflicts" and "content conflicts." When you pend an integration*, TFS compares the history of the source & target trees to see if it's safe to edit target files directly. If not, it throws a version conflict and moves to the next item. (The other types of "tree conflicts" that can be thrown are namespace conflicts and writable-file conflicts.) Nobody's examined the contents at this point -- they could be conflict-free (automergeable) or even identical. That's the client's job. When you go to resolve a version conflict, it will attempt to merge file contents together. Only if that process fails do you have a "content conflict" which requires manual merging.
Color-coding everything since the branch creation doesn't seem right at first glance, but I'm not on a TFS box right now...I'll try it tomorrow to see whether this is by design or not. In any case, it's not the cause of the conflict -- far as I can tell, you haven't hit any content conflicts yet.
*I'm deliberately avoiding the word "merge", even though that's what the TFS command is called, in order to avoid overloading that term too
eric02
That wouldn't help. As long as the resolution is AcceptMerge, we have to assume the file has new contents. Otherwise subsequent integrations would destroy the work done by the content-merge. Whether that work was trivial or some arbitary file upload is immaterial.
The baseline for comparing branch B should be last merge checkin, not the branch checkin (which could be years apart, in large systems).
That's the way it works. The repro implied by the file histories:
- create A\foo.txt
- branch to B\foo.txt
- edit A\foo.txt
- integrate to B\foo.txt
- edit A\foo.txt again
- integrate to B\foo.txt
...has no version conflicts. Both FIs should result in B\foo.txt being overwritten without fanfare.I know you're telling me the opposite, but I've never seen a conflict arise in this scenario. The only thing I can think of is that they manually pended an edit before checking in step 4.
As for the screwy content differences, my guess is that the WinForms code generation is confusing things. Autogenerated code sometimes moves around within the file without actually changing. I've seen the same thing happen elsewhere, eg <reference> tags shifting around within *.csproj files. There's not much a version control system can do about it.
[hopefully this doesn't get rendered into 2pt type...]
lholmes
you made earlier (i.e., the content merge) would be overwritten.
Conceptually, the file has been modified since the last integration:
when you checked in that integration, you checked in a new creation
formed by combining what was previously in A & B. (The server allows
the client to upload literally anything at this point.) Or think of it
this way: had you chosen AcceptTheirs instead of AcceptMerge, then TFS
would’ve simply copied the file from A to be rather than creating a new
version, thus no conflict, thus you’d see an automatic overwrite during
the subsequent integration. That danger is why AcceptMerge is the
default.
Can you elaborate on what you see “highlighted” Are you using the TFS
diff/merge tool or a 3rd-party one Automerge succeeding implies that
there are no content conflicts. In the TFS merge tool, if there are no
content conflicts, then the upper two panes should be read-only (no
“pushable” sections). Assuming this tool is working correctly, there’s
no way to resolve anything improperly other than manually typing in the
lower pane.
Nate879
Richard:
It's also interesting to note that the merge wizard states:
"In most cases, changes merged previously will not be merged again."
In my experience
"In all cases, changes merged previously will be merged again."
I don't mean to be sarcastic, but I am just illustrating that the behavior I see is completely opposite what's expected and what's indicated that should be expected.
SA.
Ashish.Net
Richard:
I am now at the point where I have an issue come up because of the behavior outlined. It's related to a WinForm resource and designer file (which are notoriously hard to read; and even more so in a split pane view...)
Here's what happend to the designer file (directly from View History in Source Control Explorer):
in branch A (the v1.0 branch...)
Initial checkin (customer was working with Beta 3 up until that point)
Bug fix
Bug fix
in branch B (the v1.1 branch)
The branch was created
Forward integration
So, after checking in changeset 79, I expect that the file is identical in branch A as well as in branch B at that point in time (after all, branch B has had no changes to this file, except for the branch and then the merge).
At changeset 101, these files are no longer identical. So, we attempt another forward integration. We get hit with a number of conflicts.
The conflicts in the designer file do not Auto Merge. So, when opening the TFS merge tool, we see 4 conflicts, in huge chunks of code, that deal with initializing the controls. Because I am not the dev responsible for that form, I don't even have a clue what these controls are for.
For example, in v1.0, it seems that some DataGrid rows or styles had been modified. Because of the unpredictability of the WinForms designer, the removed lines of code and the new lines of code do not end up in the same place. I should really send a screenshot to illustrate this, but this makes it really unmanageable to figure out what goes where. There is a bunch of blue text in the right pane, with a bunch of blue, red, and green text in the left pane, in one block of "clickable" text that is several hundred lines long.
I read your previous post (I after I got my magnifier
) and I think that the only conclusion to arrive at is that the architecture of the merge system in TFS is somewhat lacking. I think there should be a difference between a "merge" checkin and an "edit" checkin and a "merge, edit" checkin. A proper merge should not require the user to modify the file beyond the conflict tool. So, instead of presuming that someone will upload "any content" after a merge is initiated, TFS should presume that what's checked in is the merged file. If the file in the target branch has had no other edits than "merge" type checkins, it should never come up with conflicts.
Even if the file in branch B has had changes, after the first forward integration, these changes should be considered resolved. The baseline for comparing branch B should be last merge checkin, not the branch checkin (which could be years apart, in large systems).
I understand the need for the client's involvement in the compare process. I also understand that the point is to allow the user to satisfy checkin policies or run unit tests in the merge result, before checking it in. I think a solution could involve keeping track of whether a file was edited in the VS 2005 code editor when a merge is pending. Asking the user if it's indeed his/her intention to edit a file that still has pending changes from a merge operation before allowing the file to be edited would also help. If the user indeed makes changes to the file before checking in the merge result, then the pending changes should be marked "merge, edit". If not, the changes should be marked "merge" only.
Note: Yes, I realize that in this case, I can safely overwrite the branch B version with the branch A version, since branch B hasn't changed. But I'd expect the merge tool to realize this too; and auto merge properly... without even showing the conflict window. Can you imagine having to go look at the history of dozens of files, just to find out if the v1.1 version has changed, to see if you can safely overwrite the version
The really bad scenario of course will occur when that form has received updates in branch B, because then who's to tell what changes are to be kept...
Thanks for your time looking at this,
SA.
Samant B Jain
I guess this is where our thinking diverges. Conceptually, I don't think that the integration is complete until the merge has been checked in. By combining what was previously in A and B, I created a new version. I agree with that.
I guess the source of my confusion is that I believe TFS should distinguish between a merge and a merge + edit. It doesn't, so that changes that were made to the file in branch B will *always* be found again when comparing during any subsequent merge.
I use the TFS merge tool. Auto merge succeeds, yes, and yes, the upper panes are read-only. But still there is a window that lists the file as having a "conflict". When merging using the TFS merge tool, "theirs" (branch A) has the changes highlighted (=color coded) that occurred in that branch ever since the branch was created. The right pane (branch B) also contains the changes highlighted that occurred since the branch was created. Why If the file in branch B didn't change since the last integration (which I would consider the checkin after the last merge), why are the changes that happened in branch B before the last integration still highlighted. That's the cause of the conflict, and that's what I find confusing.
Perhaps I should take screen shots of the behavior I think is confusing/erroneous Do you have a blog I can contact you through
Thanks for your time,
Sven.
Henny
Richard:
Thanks for your reply.
I am not sure whether or not the merge in your forward integrate #2 uses the first merged version as the "baseline". However, even though the file in branch B has not changed since the last merge, the conflict window will appear. When viewing the changes, the changes from the first merge are still highlighted, even though they have been accepted and checked in. That is the behavior I don't expect.
So yes, Auto merge certainly works in the scenario you outlined. However, I am concerned about a scenario where there was an actual merge conflict that a developer had to resolve; and then several weeks or months later that conflict has to be resolved again because the same file was edited in branch A. You can see how that could open up problems, if the dev doing the second merge resolves the conflict in a different way than the first dev.
Thanks,
SA.
SiddCF
That’s by design – otherwise, step 6 would blow away the result of your
previous merge. By contrast, had you chosen AcceptTheirs (“copy from
source branch”) in step 4, then it would be safe to overwrite it again
in step 6.
However, the baseline for the 2nd merge should be the version from the
1st merge, not the branch creation. I just tested it and it worked as
expected.
Original file:
1
2
3
Edit in Branch A:
1 src
2
3
Edit in Branch B:
1
2 tgt
3
Forward integrate A->B, automerge:
1 src
2 tgt
3
Edit Branch A again:
1 src
2
3 src-again
Forward integrate #2, automerge:
1 src
2 tgt
3 src-again