Click here to skip to the setup instructions.

Recently, my team has been running into issues with our git merges in Visual Studio. Developers have reported alarming problems like code disappearing or duplicating. Seemingly identical files show huge blocks of differences in Visual Studio's merge tool. Developer A has a problem with a particular merge conflict, but Developer B is not able to reproduce the same.

This is a problem which is all-too-familiar for developers using Windows. Some of these issues stem from the fact that a lot of our source code runs on Unix-like systems which can introduce differences in line endings or text encoding. Developers also have their own versions of Visual Studio with their own configurations, or may not use Visual Studio at all. Our novice developers especially had a hard time because the senior developers could only scratch their heads and say, "well, it works for me!"

Eventually this became enough of a problem that we had to address it. I set out to standardize our tooling for diffing and merging code on our git repos so that everyone has the same experience when visualizing code differences, regardless of IDE or operating system. Ultimately I settled on Meld.

Meld Merge

I trialed several popular third-party diff tools and settled on Meld for our team. Meld had the right balance of simplicity and configurability to fit our needs. Meld is open source with a very active community, so it seemed like a safe bet.

Meld offers many advantages over vsdiffmerge, the tool that ships with Visual Studio:

  • Open source, cross platform
  • Can work with any IDE or from the terminal
  • Configurable text filters
  • Intuitive hotkeys
  • Ability to resolve conflicts without auto-merging

Global Configuration

For diffing and merging, Visual Studio will honor the global git configuration in C:\Users\YourName\.gitconfig. If you have never looked at this file before, it is worth opening it up and understanding the config. Visual Studio users will see something like this:

[merge]
	tool = vsdiffmerge
[diff]
	tool = vsdiffmerge
[difftool]
	prompt = true
[difftool "vsdiffmerge"]
	cmd = \"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\Common7\\IDE\\CommonExtensions\\Microsoft\\TeamFoundation\\Team Explorer\\vsdiffmerge.exe\" \"$LOCAL\" \"$REMOTE\" //t
	keepBackup = false
[mergetool "vsdiffmerge"]
	cmd = \"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\Common7\\IDE\\CommonExtensions\\Microsoft\\TeamFoundation\\Team Explorer\\vsdiffmerge.exe\" \"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\" //m
	keepBackup = false
	trustExitCode = true
.gitconfig on Windows

vsdiffmerge, the built-in tool that ships with Visual Studio, is configured globally as the default tool for diffing and merging code. Whenever you compare two files in Visual Studio, or you open the conflict resolution window, Visual Studio is triggering the commands shown above to launch vsdiffmerge.

If we change vsdiffmerge to something else, like Meld, Visual Studio will honor that choice as well. And because this is a global configuration, every IDE should follow suit. This is exactly what happens when you run git difftool or git mergetool.

See the instructions below to update your global config to use Meld.

Installation on Windows

Here is a basic setup that we are trying out with all of our developers. This is a good starting point if you are using git with Visual Studio or any IDE really.

Meld
  1. Install Meld by downloading the Windows msi at https://meldmerge.org
  2. Open Git Bash, the terminal which ships with Git for Windows. If you do not have Git Bash, install it from https://gitforwindows.org/
  3. In the Git Bash terminal, run the following command. Copy it from here and right-click paste into the terminal, press enter to run it.
git config --global merge.tool meld &&
git config --global mergetool.meld.cmd '"C:\Program Files (x86)\Meld\Meld.exe" --label "LOCAL>BASE<REMOTE" --auto-merge "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"' &&
git config --global mergetool.meld.keepBackup false &&
git config --global diff.tool meld &&
git config --global difftool.meld.cmd '"C:\Program Files (x86)\Meld\Meld.exe" --label "LOCAL|REMOTE" "$REMOTE" "$LOCAL"' &&
git config --global difftool.meld.keepBackup false
Git Global Configuration

4. Test by comparing files or resolving conflicts in Visual Studio. Meld should be launched in a new window for every operation.

Advanced Configuration

Running the command above will add some new settings to your .gitconfig file.

[mergetool "meld"]
	cmd = \"C:\\Program Files (x86)\\Meld\\Meld.exe\" --label \"LOCAL>BASE<REMOTE\" --auto-merge \"$LOCAL\" \"$BASE\" \"$REMOTE\" --output \"$MERGED\"
	keepBackup = false
[difftool "meld"]
	cmd = \"C:\\Program Files (x86)\\Meld\\Meld.exe\" --label \"LOCAL|REMOTE\" \"$REMOTE\" \"$LOCAL\"
	keepBackup = false
Excerpt from .gitconfig

These are the commands that are executed for your diffs and merges. Here are some additional tweaks you can make.

  1. In the mergetool cmd setting change --auto-merge to --diff. This will disable auto-merging when you resolve a conflict. This way you can start with a clean base file and merge everything by hand. You can still manually auto-merge in Meld by choosing Changes > Merge All.
  2. In the mergetool cmd setting, swap "LOCAL" and "REMOTE" if you prefer showing the local changes on the right side instead of the left side (this is how vsdiffmerge displays).
  3. Set the mergetool setting keepBackup = true. This way git will save backup copies of the LOCAL, REMOTE, BASE, and MERGED files. Once you are done merging you can manually delete the backups.
  4. Add a new setting under mergetool, trustExitCode = true. This way when you save your changes and exit Meld gracefully, Visual Studio will automatically accept and stage your merged result.

I like to keep a few commands commented out so I can easily toggle between them without screwing something up:

[mergetool "meld"]
	cmd = \"C:\\Program Files (x86)\\Meld\\Meld.exe\" --label \"LOCAL>BASE<REMOTE\" --auto-merge \"$LOCAL\" \"$BASE\" \"$REMOTE\" --output \"$MERGED\"
	# cmd = \"C:\\Program Files (x86)\\Meld\\Meld.exe\" --label \"LOCAL>BASE<REMOTE\" --diff \"$LOCAL\" \"$BASE\" \"$REMOTE\" --output \"$MERGED\"
	keepBackup = false
Excerpt from .gitconfig

Going Back to vsdiffmerge

If you screw something up or you just want to go back to the built-in tool in Visual Studio, the best way to roll everything back is to let Visual Studio reset the .gitconfig for you. You can do this by going into the Tools > Options window, then navigating to Source Control > Git Global Settings. From there, click the respective Use Visual Studio link for the operation that you want to change. (this is how to do it in VS2019, but the steps may differ for other versions of VS).

Visual Studio Diff and Merge tools

Once you click Use Visual Studio, your .gitconfig will be updated automatically. This is a bit safer than editing the file by hand which could introduce mistakes.

Thanks for reading!