To magically fix all of your problems, type ‘Resolve’


Ok, I probably can't quite deliver on a promise like that (instead, I suggest you simply buy an easy button). But, when it comes to the various things that can go wrong in your Version Control workspace, "resolve" is the command that's responsible for putting things back together.

Resolve handles three "classes" of conflicts - version conflicts, namespace conflicts, and local overwrite conflicts. By and large, there are three commands (currently) that can generate conflicts - get, checkin, and merge.

The classic version conflict scenario (in the parallel development world) is the situation where you try to get or checkin a file, but someone else has checked in one or more new versions since you checked it out. Depending on how the two files changed, we may be able to automatically resolve the conflicts.

For example, if you added 3 lines to the end of the file, and someone else checked in a delete of the first line of the file, we can delete that line from your file and then you'll be up to date with the merged file (yes, we've overloaded the term 'merge'). Or maybe you made content changes to the file and someone else just renamed it. We can move the file in your workspace but preserve your changes, and again you'll be ready to check in. There are many other scenarios (many, MANY others). We'll ask you if you want to attempt to automatically resolve the changes, along with various appropriate 'manual' resolution options (keep your changes, discard your changes, use a manual merge tool, etc.).

The next kind of conflict is a namespace conflict - these arise when two items want to have the same fully-qualified name at the same time. The classic example is where you try to add a file and someone else has (presumably recently) checked in a file with the same name. There are other scenarios - you try to rename a file but someone just undeleted a file with the same name, for example. In these cases, we can't automatically fix the problem. We're still tweaking the final behavior and UI, but the current thinking is that you'll be prompted to either rename your local item, or keep it and pend a rename of the conflicting item, or undo your change. Get, checkin, and merge can all generate namespace conflicts.

The final conflict type is pretty straightforward compared to the other two. There are situations where, during a get or merge, something about the state of your workspace blocks the server from moving, writing, or overwriting one or more files. We'll prompt you to try the operation again (in case you fixed whatever the problem was on your own, perhaps by changing permissions on a folder), or overwrite the item, or cancel (as in, let me fix it!). The overwrite scenario is the classic one that SourceSafe users may be familiar with - you couldn't check out the file for some reason, so you just cleared the readonly flag and made some changes yourself. Overwrite gives the server permission to overwrite the local contents with the version you specified in get (or the tip, if you didn't specify a version).

The nice thing to note about using resolve, instead of just retrying get, is that it will "finish the get". So, if you were trying to sync your workspace to a specific point in time, or changeset, etc., resolve will finish getting your workspace into that state, instead of you having to fix the problems and then run get again (and possibly reentering a complex date or label specification).

As you can probably imagine, things get slightly more complicated when merge is involved. If there's a conflict when trying to merge change between items, you'll be prompted whether to keep the merge source's version, or the merge target's, or to automatically or manually merge the differences (if appropriate), and you'll have similar options where renames are involved as above.

We also are working on some UI to streamline the process. We want you to be able to select a course of action for a whole class of conflicts (for example, automatically merge all version conflicts, ignore namespace conflicts so I can address them individually, and overwrite locally writable items).

Any questions about resolve? Obviously there's a lot more to the story where various wacky scenarios and edge cases come into play...

Comments (10)

  1. 99% of the time, in the "local overwrite" case the behavior I actually want is something like "pretend I’d checked out the file as of the last version that I did a ‘get’ operation on, and do a ‘merge’ resolve operation accordingly".

    For example, suppose we have version 1 of Hello.txt with the contents:

    Hello world!

    Goodbye world!

    Now I fail to checkout Hello.txt so I make it locally modifiable and add a new line:

    Hello world!

    Goodbye world!

    Hello again world!

    In the meantime someone else checked in version 2 with a change to the first line:

    Hello there world!

    Goodbye world!

    When I do a get, it’s pretty obvious what behavior I want and there’s no fundamental reason the source control system can’t provide it. It knows that my working copy corresponds to version 1, and it can tell simply enough that it doesn’t actually match version 1 (not least because it’s writable). So when it’s faced with this conflict it should be trivial to pick version 1 as the common ancestor and merge my local version with version 2:

    Hello there world!

    Goodbye world!

    Hello again world!

    I’ve complained on various blogs that it sounds like the offline support in Team Foundation is barely improved over SourceSafe, and hopeless compared to CVS’s (and even CVS’s still sucks compared to what you’d really like to be able to do). But if the "local overwrite resolve" operation were smart like this, that would be enough to match (if not improve on) CVS’s functionality. It would change offline use from "horribly painful" to "comfortably tolerable". Still a long way from "excellent" but a massive, massive improvement over today’s world.

  2. Stuart, I have mostly good news.

    For the most part, your specific example is pretty decent in Hatteras. When you were ready to get ‘back online’, you’d run h checkout Hello.txt, which would move it from being just writable to actually being checked out (it does NOT clobber your changes). Then you’d run get, and you’d get the version conflict. Your specific scenario CAN be automatically merged, so you’d end up with the merged file exactly as you described. I even tried out your exact scenario just now to make sure 🙂

    In the case where there wasn’t a newer version on the server, you’d just check yours out and then check it in.

    The thing we’re missing is something that looks at all of your local files and figures out which ones you ‘edited offline’, and checks them out for you.

  3. Awesome 🙂

    "Something that looks at all of your local files and figures out which ones you edited offline and checks them out for you" is probably less than a screenful of Perl code that I can write myself. I’d have to use an "h status" command and parse the response (I’m assured that the output of the various h commands are scriptability-friendly, no filename truncation like ss.exe output) to see which files I had checked out, and then compare that with the results of a directory scan looking for non-readonly files. Pretty trivial stuff 🙂 If I wanted to be clever I could combine that with an "h diff /format:brief" or whatever to tell me whether files were really changed or not regardless of their writability.

    The most interesting part of your response is the implication that "h checkout" checks out whatever version you last got (version 1 in my example), rather than automatically incorporating a "get" operation as well. Is this only because the file was locally writable and/or modified, or is this always the behavior? (either way it’s cool, but I’m intrigued…)

  4. Stuart,

    Yes, the command line client has scripting in mind. We’ll be looking for feedback anywhere we do things that make this great, and especially places where we could make it better – your filename truncation is a classic example of things we’ll want to find and fix during the CTP/Beta process.

    We’ll always *only* checkout the file, rather than issuing a get in the process. There are various scenarios where you want a specific, non-tip version to pend changes against; for example, if a bug is reported in some specific build, you might want to sync back to a label that describes that exact build, repro the bug, fix it, THEN do a get to latest to merge your bugfix with subsequent changes to the affected files. It’s a break from the SourceSafe mentality on checkout, but I like it better this way. Since you might always have to deal with newer versions by the time you check in anyway…

    Note that we will issue a warning if there’s a newer version "already" when you check out. So if you didn’t mean to check out an earlier version, you can run get and resolve to get to latest. Or you could undo your checkout, run get to get to latest, and check out again.

    We also report if other people already have it checked out (again, just a warning), so you’ll have some inkling that some toe-stepping may be in the near future.

    We have a set of files that our whole QA team finds the need to update periodically. So when I check one of them out, it’s quite common to see that 3 or 4 other people also have it checked out. It’s also quite common to see that several versions get created while I’m working on a modification. So, I often run get two or three times along the way, incorporating changes as I go, then finally do one last content merge when I’m ready to check in. It works out pretty well in our case, since we’re usually modifying different areas of the files in question, which means the changes can usually be automatically resolved with no conflicts (or build breaks – a whole different animal, of course).

  5. All of those answers are exactly what I’d hope them to be. That’s awesome, awesome news and it addresses one of my two biggest worries about VSTF (the other being the lack of VS2002/2003 integration – I’ve been specifically told in other blogs that this is *not* planned)

    One particular place where this merging behavior will be a *huge* improvement will be with VS project files. It’s a major bone of contention right now that only one person can be in the middle of a change that involves adding or deleting files at a time. Decent merging on the project file would be a godsend.

    Note that in a *really* ideal world you ought to be able to do better on the project file than on an arbitrary text file. Consider this project file (syntax is approximate; I know it’s changed since VS2003 anyway):

    <Files>

    <file name="A.txt"

    …/>

    <file name="B.txt"

    …/>

    </Files>

    If one person adds an "A1.txt" and another adds an "A2.txt", a pure text-file style merge on the project file would treat these as a conflict because the new lines were added in the same place (between A and B in alphabetical order). But knowing the project file format it’s possible to resolve this conflict and know that both insertions should be honored and "A1.txt" goes first.

    I’m not sure how to deal with this issue architecturally – the TF layer is rightly well below the layer that understands project files. Perhaps a plugin architecture is needed that can provide filetype-specific help to TF on how to resolve merge conflicts.

    (Just to be clear – I’m still really happy to learn this news even if TF doesn’t have any answer to this obscure class of project file conflict. It’s still vastly improved over today’s world and I’ll be thrilled to get the chance to use it. I just thought of the project file thing while I was digesting the implications of your comment, and I thought it would be worth mentioning, either to see if you have an answer already or as a suggestion for a future release)

  6. Well, I can see your point, that a tool "aware" of project structure might be able to reconcile both changes. But, I don’t think you can get away from a conflict in the A1/A2 case – they’ll always be different changes to the same location in the file. Your tool would have to actually be smart enough to go see that files with both those names now exist, or something.

    In the case where one person adds A1 and another adds B1 – and assuming you’re right in saying that VS maintains a sorted order – even our built-in tools will be able to recognize these as two distinct changes.

    Also, we’re planning on shipping with an XML diff/merge tool as well as a more typical text tool, so if you do have to manually reconcile changes in a project file, you’ll at least have an XML-aware tool to do it with.

  7. Yeah, I wasn’t suggesting that tf could handle this case without special help from something that understands the filetype.

    And you’re right, the 90% case is where the files are added in different places in the list and can be merged just fine with builtin tools.

    I guess really I’d have to say I consider it a VS-level bug rather than a TF-level one. Anything that exposes the implementation details of the syntax of the project file to the end user – especially in the form of a conflict that requires manual resolution only if two files were added that are alphabetically adjacent in name – is a user-experience problem. But it’s perfectly reasonable to say that handling this case is really VS’s problem, not yours.

    The *most* I’d expect of TF here is to allow applications calling it through its API to be able to programmatically identify merge failures and programmatically resolve them. Then VS could intercept merge conflicts in the project file and apply its greater knowledge of the filetype to see if it can do better resolution than TF can alone.

  8. Adam Singer says:

    So, this has been awhile coming. Let’s blame that on the combination of 2 zillion screenshots and the

Skip to main content