Whenever you use a source control tool and enable the multiple check-out option (allow several users to edit a file at the same time), you often have to merge multiple versions of a file after resolving conflicts. Let’s imagine for instance that a user A checks-out a file and begins editing it whilst another user B checks-out the same file and also begins editing it at the same time. The first user who will validate and check-in his pending changes will have no problem at all. On the other hand, the second user might face some issues because the version he obtained at the beginning is different than the latest version that is now present on the server (the one that has just been checked-in by A). Therefore you will have to decide which changes must be kept : the ones that are on the server, the ones made by B, or both. This is where the merge tool comes into action. It will allow you to see the differences that exist between both versions of the file. Then, you can either choose by yourself the version to keep for each conflict, or you can let the tool follow its algorithm to automatically merge the files. The default tool that was used by Visual Studio prior to 2012 to resolve Team Foundation Server conflicts was all but a gift as you often had to manually resolve them to avoid unpleasant surprises. This is due by and large to the fact that it was part of the old generation of compare/merge tools that only compare the two new versions of the file without using the original one (2-way merge). Although this tool is now using a 3-way merge algorithm, I personally still don’t find the Visual Studio interface for resolving conflicts user-friendly. But don’t worry, if this tool does not meet your expectations, you can use another one without changing the way you work in Visual Studio. For this purpose, open the Tools/Options menu, then browse to the Source Control section in which you will find a sub section called Visual Studio Team Foundation Server (Figure 1).
Below all options of this screen you can see a Configure User Tools button. Click it in order to configure your tool. The window that gets opened is empty by default (Figure 2).
Click the Add button to open the configuration window (Figure 3). Here you have to specify the operation type (compare or merge) and all file extensions for which you want your new tool to act as a replacement for the default tool.
Notice that you can only choose one operation type at a time. You’ll simply have to validate one first time and then, after being back to the previous window, click the Add button again to start the configuration process of the second operation type. About the other options, you must specify the path to the tool you want to use as long as the parameters it needs to receive. To correctly fill in the parameters according to the tool you want to use, please read the section below that describes the meaning of each parameter and specify the required command arguments for the most common tools for both compare and merge operations. This is crystal clear. And except if you are using a tool from outer space (I’m just exaggerating a little), yours should be listed.
- %1 = Original file (in compare mode, the pre-changes file, in merge, the “server” or “theirs” file, the file that is the base file after “their” changes were applied)
- %2 = Modified file (in compare mode, the post-changes file, in merge the “yours” file – the base file with “your” changes applied)
- %3 = Base file (in the 3-way merge operation, the file which both “theirs” and “yours” are derived from – the common ancestor. This doesn’t mean it’s the version the changes were based from, since this may be a cherry-pick merge)
- %4 = Merged file (The output file for the merge operation – the filename that the merge tool should write to)
- %5 = Diff options (any additional command-line options you want to pass to your diff tool – this comes into play only when using “tf diff /options” from the command-line)
- %6 = Original file label (The label for the %1 file)
- %7 = Modified file label (The label for the %2 file)
- %8 = Base file label (The label for the %3 file)
- %9 = Merged file label (The label for the %4 file)
|Diff Merge (default)||diffmerge.exe||Compare||%1 %2 %6 %7 %5 /ignorespace|
|Diff Merge (default)||diffmerge.exe||Merge||/merge %1 %2 %3 %4 %6 %7|
|WinMerge||winmerge.exe||Compare||/ub /dl %6 /dr %7 %1 %2|
|WinMerge||winmerge.exe||Merge||/ub /dl %6 /dr %7 %1 %2 %4|
|Beyond Compare||bc2.exe||Compare||%1 %2 /title1=%6 /title2=%7|
|Beyond Compare||bc2.exe||Merge||%1 %2 /savetarget=%4 /title1=%6 /title2=%7|
|Beyond Compare 3||Bcomp.exe||Compare||%1 %2 /title1=%6 /title2=%7|
|Beyond Compare 3||Bcomp.exe||Merge||%1 %2 %3 %4 /title1=%6 /title2=%7 /title3=%8 /title4=%9|
|Araxis||compare.exe||Compare||/wait /2 /title1:%6 /title2:%7 %1 %2|
|Araxis||compare.exe||Merge||/wait /swap /a3 /3 /title1:%6 /title2:%7 /title3:%8 %1 %2 %3 %4|
|KDiff3||kdiff3.exe||Compare||%1 –fname %6 %2 –fname %7|
|KDiff3||kdiff3.exe||Merge||%3 –fname %8 %2 –fname %7 %1 –fname %6 -o %4|
|SourceGear DiffMerge||DiffMerge.exe||Compare||/title1=%6 /title2=%7 %1 %2|
|SourceGear DiffMerge||DiffMerge.exe||Merge||/title1=%6 /title2=%8 /title3=%7 /result=%4 %1 %3 %2|
|TortoiseMerge||TortoiseMerge.exe||Compare||/base:%1 /mine:%2 /basename:%6 /minename:%7|
|TortoiseMerge||TortoiseMerge.exe||Merge||/base:%3 /mine:%2 /theirs:%1 /basename:%8 /minename:%7 /theirsname:%6 /merged:%4 /mergedname:%9|
|Visual SlickEdit||win\vsdiff.exe||Compare||%1 %2|
|Visual SlickEdit||win\vsdiff.exe||Merge||%3 %1 %2 %4|
From now on, Visual Studio will systematically use your tool for all conflict operations that you configured.
Even if the auto-merge process often works fine, there are some cases where it does not behave as expected. To avoid any problem, it is important to respect some basic rules :
- When you need to add a file to a project, check-out the project, add the file and check-in the project and the file directly. Even if it is a new class, it will be empty in the source control but it will allow other users to work with the latest version of the project and it will build. You can then just check-out your file and continue the implementation without affecting other users.
- When you need to add or modify language resources (i.e. resx files), check-out the files, make your modifications and check them in directly. You never need to work on resource files for hours so why would you keep them checked-out ?