I finally got tired of reading diff outputs from git on the command line, and decided to hook up a visual diff and merge tool. After piecing together hints from various posts around ye olde intraweb I’ve now got somethings that works. I am using Git on MSys to get Git working on Windows via a PowerShell command line, but a similar setup might work via Cygwin or via the cmd.exe
command line.
Setting up a diff tool
git difftool
instead.The easiest way I found to do this was to create a shell script wrapper for your diff tool of choice. To make things easy on me I put the script, git-diff-wrapper.sh
in C:\Program Files\Git\cmd
, which is in my Path
environment variable. The file contents looks like this:
#!/bin/sh # diff is called by git with 7 parameters: # path old-file old-hex old-mode new-file new-hex new-mode "C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$2" "$5" | cat #"C:/Program Files/WinMerge/WinMergeU.exe" "$2" "$5" | cat #"C:/Program Files/KDiff3/kdiff3.exe" "$2" "$5" | cat
The basic format of this is stolen directly from this post on the Msysgit site. Provided your diff tool can be called from the command line, you’ll be able to set it up to work with Git using this template. In this case I’ve used it to setup a call to Sourcefear’s DiffMerge, a nice free (as in beer) diff and merge tool.
You’ll also see I’ve commented out calls to WinMerge and KDiff3, which are both free as in beer and speech. I ended up settling on DiffMerge because it is purdy (unlike KDiff3 – sorry), and also does 3-way merges (unlike WinMerge, which was my previous diff tool of choice).
The next step is telling Git about your wrapper. In your home directory (C:\Users\(username)
or the corresponding Documents and Settings equivalent) Git will normally have created a .gitconfig
file. If not then go ahead and create one. You’ll need to have the following section in there:
[diff] external = C:/Program Files/git/cmd/git-diff-wrapper.sh
We can now use git diff
and it will fire up our diff tool of choice.
Setting up a merge tool
I had more trouble getting a merge tool working, largely because putting references to paths like C:/Program Files/...
in .gitconfig
seems to bork when used here. Again I ended up using the wrapper approach, creating git-merge-diffmerge-wrapper.sh
at C:\Program Files\Git\cmd
to call DiffMerge. This file ended up looking like this:
#!/bin/sh # Passing the following parameters to mergetool: # local base remote merge_result "C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$1" "$2" "$3" --result="$4" --title1="Mine" --title2="Merging to: $4" --title3="Theirs"
I unashamedly stole this from Alexander Groß’s post on getting DiffMerge running on Cygwin-based Git (with slight modifications, any faults are mine :)). We can then wire this up in .gitconfig
again:
[merge] tool = diffmerge [mergetool "diffmerge"] cmd = git-merge-diffmerge-wrapper.sh "$PWD/$LOCAL" "$PWD/$BASE" "$PWD/$REMOTE" "$PWD/$MERGED" trustExitCode = false keepBackup = false [mergetool "kdiff3"] path = C:/Program Files/KDiff3/kdiff3.exe keepBackup = false trustExitCode = false
Now remember that C:\Program Files\Git\cmd
is on my PATH
, so I can set the command to call git-merge-diffmerge-wrapper.sh
without fully qualifying the path. The details on the arguments are available from the git-mergetool(1) man page. I’ve also left in a KDiff3 version that seems to work too (Git has some built in support for KDiff3 I think, which is why you can get away with only specifying the path).
Time for a test drive
Let’s make sure everything’s in working order. I’ll open up a PowerShell window and let’s see how we go (you’ll have to excuse me for using old DOS commands instead of fancy PowerShell ones, I’ve only just switched to PS after running into various issues with the cmd.exe
command line).
PS> mkdir HelloWorld PS> cd HelloWorld PS> git init Initialized empty Git repository in C:/Development/Git/HelloWorld/.git/ PS> echo Hello World! > hello.txt PS> git add hello.txt PS> git commit -m "Initial commit" [master (root-commit)]: created 2a2cf34: "Initial commit" 1 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 hello.txt PS> git checkout -b helloGit Switched to a new branch "helloGit" PS> echo Hello Git! > hello.txt PS> git add hello.txt PS> git commit -m "Update from helloGit branch" [helloGit]: created e71437b: "Update from helloGit branch" 1 files changed, 0 insertions(+), 0 deletions(-) PS> git checkout master Switched to branch "master" PS> echo Hello World! Hello indeed! > hello.txt PS> git add hello.txt PS> git commit -m "Update from master" [master]: created 5dee19d: "Update from master" 1 files changed, 0 insertions(+), 0 deletions(-) PS> git merge helloGit warning: Cannot merge binary files: HEAD:hello.txt vs. helloGit:hello.txt Auto-merging hello.txt CONFLICT (content): Merge conflict in hello.txt Automatic merge failed; fix conflicts and then commit the result.
echo
to stream data into hello.txt
the files have ended up in binary mode. Let’s ignore that as it is just to get an easy demo going. The important thing is we now have a merge conflict to resolve.If we now type in git mergetool
Git ask’s us if we’d like to run our merge tool. We can hit enter and up pops DiffMerge. If you wanted KDiff3, we could have called git mergetool -t kdiff3
, or any other merge tool in our .gitconfig
(by default the tool specified in the merge.tool
config option is used).
PS> git mergetool Merging the files: hello.txt Normal merge conflict for 'hello.txt': {local}: modified {remote}: modified Hit return to start merge resolution tool (diffmerge):
Resolve the merge conflict however you like and then try this:
PS> echo Wow, it worked! > hello.txt PS> git diff
Hooray, we have our diff tool working! We can also run commands like git diff HEAD~ HEAD
and git diff helloGit master
and get the output via our diff tool.
Conclusion
This setup earns the coveted Works on My Machine certification, but even if that’s the only place it works then hopefully it still gives you enough information to configure your Windows diff and merge tools for use with Git.
If you hunt down the relevant command line options you should be able to get pretty much any tool working: Beyond Compare, p4merge, TortoiseMerge etc.
Hope this helps.