In my previous post I described a VCS branching plan that will remove the need to initiate code freezes. A few of my friends pointed out that their teams do not use that or similar methodologies not because they were unaware of such simple possibilities, but because performing reverse integrations (or any kind of merge) is so difficult with TFS (their ALM tool of choice), that most developers do everything they can (e.g. initiate code freezes) to avoid having to perform a lengthy and painful merge.
My advice is twofold. First, methodology-wise: Merge often! The more often you merge, the smaller and simpler the merge will be. As a rule of thumb, and assuming you are using the simple branching plan I suggested last week, you will want to merge every time you fix a bug (remember – you only merge when doing a reverse integration from a release branch to the main branch). For more complex plans, that have the actual development done on a separate branch from Main, requiring forward integration merges (i.e. from “Main” to “Dev”), you will want to merge on a daily basis, or whenever you know that there’s something to merge (from a release branch or a different development branch).
My second advice, to which I will dedicate the rest of this post, is to replace the diff / merge tool!
It is a well known fact, to those who know it well, that Microsoft have outfitted TFS with a less-than-adequate diff/merge tool, especially when compared to those available to users of SVN, Git, and Mercurial (to name a few).
How so? The primary issue I have with TFS’ default diff tool, is that it shows me which lines are conflicting, but it’s up to me to find out just how they differ from each other.
This is how the default tool shows the difference:
Found the difference? Difficult, isn’t it? The default diff-tool provided with TFS marks the lines that are different; it doesn’t show you what the actual change is.
Here’s what it looks like in KDiff3:
See the difference now? The actual changes are marked, not just the line. Makes comparing the code with the other version much simpler. By the way, in case you are visually impaired, what I did was replace the word “TFS” with “custom”.
The second, and more important part of the tool, is the actual merging capabilities. I’ve got a major gripe with the default tool as well. TFS’ merge tool performs a 2-way merge, where as other tools (KDiff3, for one) performs a 3-way merge.
What’s the difference you ask? Basically, a 2-way merge compares two files and attempts to best-guess what the differences between them are – this is rather error-prone, and thus requires more human intervention. 2-Way merges are good enough for simple merges, like those done every time you commit (or check in) changes to your code base. When you are trying to resolve a conflict between your changes, and the changes somebody else made, you just might be in for what is (dis)affectionately known as merge-hell. This happens when two developers made changes to the same source file, especially when the changes are located close to each other (i.e. same or consecutive lines of code).
3-way merges, on the other hand, compare both versions of the file to their parent version, and therefore can focus on comparing the changes made, rather than the complete files. This allows for a more reliable automatic merge, which means that the merge will be much simpler. Even if an automatic change is not possible, the tool’s focus on the actual changes helps the developer decide whether to include one or both changes.
Okay, I’m Convinced! Give Me the Goods!
Good! Luckily, it is very easy to replace the Diff/Merge tool in TFS. This is done on the client side, from within visual studio.
Following is a step-by-step guide for how to do replace the merge tool. I know that most of you don’t need this level of detail, but for those beginning developers or those of you whose brains have been terminally damaged by long hours of merge-hell, here it is:
Press on the Add… button to add diff and merge custom tools. Doing so will open the following window (so many windows; I hope you aren’t confused):
Filling in the information is rather simple; You add the file extensions for which you wish the tool to be used (comma separated, prefixed with a period like “.cs”). You then select the operation you wish to associate with the tool. Note that for diff/merge tools there are two commands you wish to use – Compare and Merge. Remember to do both.
Next you select the command – that’s the actual tool you are going to use. KDiff3 is a great tool, both free and powerful (not to mention popular with the Git and Mercurial crowd. If they like it must be cool), and is my tool of choice. Other popular choices include Beyond Compare (version 3 and up only, as prior versions do not support 3-way merges, and you really want that for your reverse-integration merges), DiffMerge, and TortoiseMerge (especially if you were dragged away from SVN kicking and screaming).
Finally you enter the command arguments. If you are daunted (as I often am) by having to find out what arguments you need, then fear not! I found this great post from a few years back, that lists a whole bunch of tools with the command-line arguments you need in order to use for TFS.
For KDiff3, use the following argument values:
Compare: %1 –fname %6 %2 –fname %7
Merge: %3 –fname %8 %2 –fname %7 %1 –fname %6 -o %4
Selecting a better diff/merge tool will greatly improve your merging experience, and hopefully alleviate most of your pain when performing those reverse integrations. Remember to merge as often as you can, so that each merge will be small and painless.
If anybody has any other ideas, experiences on how to make using TFS’ version control system easier, please share!