Conflict Resolution in Teamprise

January 16, 2007

One of my coworkers asked me for clarification on the conflict resolution dialog in Teamprise. If you're not used to version control that allows multiple checkouts - say you're coming from the rather limited world of Visual SourceSafe, for instance - this could be somewhat vague. I thought I'd post a brief explanation of the conflict resolution process in Teamprise and TFS.1

For this example, we'll use the simplest of conflicts, what TFS calls "Version Conflicts." These arise when two people have both made changes to a file: say that both you and Bob get $/Foo/Bar.txt at the same time. Bob makes changes to this file and checks them in. You are now out of date with the server, and you have a Version Conflict. When you try to check this file in, or do a Get Latest on this file, you will be prompted to resolve this conflict with a dialog that looks something like this:

Version Conflict Dialog

This dialog allows you to choose the action Teamprise or TFS should take to bring your changes in sync with the server's changes. You have two all-or-nothing choices: accept all of your changes, discarding the changes on the server, and accepting all the server changes, undoing yours.2 For simple conflicts, you also have a more advanced option, the "Merge changes for me", or automerge option. This is available if the changes Bob made don't "conflict" with the changes you made.

Yes, your conflict can have conflicts. If you both made changes to the same lines, then your changes are in conflict. The "Changes" line in the Conflict Resolution dialog will tell you quite a bit about what's going on with the files in a very concise way. The Changes line will show the following information:

Changes: n local, m server, k common, j conflicts

Where:
n is the number of changes you've made that remained unchanged in the server's version
m is the number of changes on the server that remain unchanged in your version
k is the number of changes that occurred in both your version and the server's version, but the changes are identical
j is the number of changes that occurred in both your version and the server's version that are not identical

Let's look at an example:

Original VersionYour ChangesBob's Changes
one1one
twotwotwo
threethree3
fourfour4

In this case, you have made changes to different portions of the file, and so your changes are not conflicting at the file-level. Your Changes report will look like this:3

Changes: 1 local, 1 server, 0 common

Since the changes are isolated, you're offered the "Merge changes for me" option. If you select this, your changes will be automatically incorporated with Bob's changes. Let's use colors to make it clear where these files came from:

Original VersionYour ChangesBob's ChangesMerged Version
one1one1
twotwotwotwo
three333
fourfour44

Automerge isn't exactly a panacea, though. It only looks at regions of the file to determine whether your changes overlap with Bob's changes, it doesn't look at the context. Just because the changes were isolated in different parts of the file doesn't mean that the file makes sense, will compile, or will run properly. Imagine the following:

Original VersionYour ChangesBob's ChangesMerged Version
int i = 10;int i = 10;// get rid of i// get rid of i
int j = 20;int j = i;int j = 20;int j = i;

Strictly speaking, this file was automerged. Unfortunately, the results are garbage - this new file won't compile. Clearly automerge is often helpful, but you still need to pay attention to what's going on with your files.

So far we've looked at non-conflicting changes - those where you and Bob edited independent parts of the file. But what if you changed the same lines? Imagine the following changes:

Original VersionYour ChangesBob's Changes
oneoneone
two2II
three33
fourfourfour

Clearly, this is a conflict -- line two was changed in both places. In this case, you'll get what appears to be an odd report at first:

Changes: 0 local, 0 server, 1 common, 1 conflict

The 1 common is easy to recognize - both you and Bob changed line three to "3", the same value, and the change was in common. The 1 conflict is also easy to recognize - both you and Bob changed line two independently. But why are there 0 local and 0 server changes? And how are there conflicts if there were no changes? Remember, local changes are defined as those which were not mutual conflicts (be it changes in common or conflicts.)

Also note that now that there's a conflict, the "Merge changes for me" option is disabled. Teamprise and TFS will refuse to attempt to automerge a file with conflicting changes, you will be required to merge manually. You can do this by cancelling the conflict resolution, making changes to your version manually, then going back to the conflict (via attempting a Get Latest or a Checkin) and accepting your version.

Merging conflicts is going to be made easier in the upcoming Teamprise 2.1 release. Teamprise 2.1 adds support for external merge tools. These can be configured for all files, or on a per-file-type basis (by file extension.) This allows you to use your favorite diff/merge tool to interactively merge changes in your conflicts. Here's KDiff3 running on MacOS X, resolving a simple conflict:

KDiff3 on MacOS X

Conflicts can arise in any source code control software, and the more powerful a solution is, the more likely they are to occur. Fortunately, Teamprise and TFS have a rich conflict resolution system to allow you to resolve conflicts quickly, and accurately, and get back to work.

Footnotes

  1. Although I'll be using Teamprise for these examples, our conflict resolution is modeled after TFS for lack of confusion.

  2. Usually not what you want, unless you've coordinated with Bob to incorporate his changes, or your changes are orthogonal and you wish to pick the superior solution.

  3. Why not 2 server changes? After all, two lines were changed... The comparison isn't line-based, it's region based. One "region", comprised of two lines, was modified by Bob, and since this region doesn't overlap the region edited by you, the changes do not conflict.