DiffMerge is an free 3-way merge tool by SourceGear that runs on Windows, Mac, and Linux.
With the 3.3.0 release (April 2009), DiffMerge is compatible with Mercurial external merge feature. When the --result=file argument is used, DiffMerge writes the merge result to the given file and exits with 0 (merge resolved), 1 (merge aborted), or 2 (other error). Note that DiffMerge does not handle binary files so you'll want to configure another tool for them.
You can also use DiffMerge as an external diff viewer using the extdiff extension feature. With the changes below, you can type hg diffmerge instead of hg diff.
To enable both diffing and merging with DiffMerge, add the following to your .hgrc or Mercurial.ini file:
[ui] merge = diffmerge [extensions] hgext.extdiff = [extdiff] cmd.diffmerge = /usr/bin/diffmerge [merge-tools] diffmerge.executable = /usr/bin/diffmerge diffmerge.args = -merge -result=$output -t1="Local Version" -t2=$output -t3="Other Version" -caption=$output $local $base $other diffmerge.binary = False diffmerge.symlinks = False diffmerge.gui = True
On Windows, the executable should be: c:\Program Files\SourceGear\DiffMerge\DiffMerge.exe.
On Mac OS X, please also install the command-line shell script that was included on the DMG; see the README for details.
Prior to the 3.3.0 release, DiffMerge was not directly compatible with Mercurial. It always returns 0 as its exit code, which causes Mercurial to assume that the merge was successful. It also merges to one of the Mercurial temporary files instead of the local file. The python script below fixes both of these problems. It runs on Python 2.5 and later. (On Mac and Linux, you will need to update the paths in the locations list to point to where you have DiffMerge installed.) Since DiffMerge does not handle binary files you will want to add the following to your hgrc file:
hgrc files changes
[ui] merge = diffmerge [merge-tools] diffmerge.binary = False
locations = ['C:\\Program Files\\SourceGear\\DiffMerge\\diffmerge.exe', 'C:\\Program Files (x86)\\SourceGear\\DiffMerge\\diffmerge.exe', '/Applications/DiffMerge.app/Contents/MacOS/DiffMerge', '/usr/bin/diffmerge'] import hashlib import sys import subprocess import os import shutil def hashFile(filename): m = hashlib.md5() with open(filename) as f: m.update(f.read() + str(os.path.getmtime(filename))) return m.digest() local = sys.argv base = sys.argv other = sys.argv validLocations = filter(os.path.exists, locations) if len(validLocations) == 0: print("DiffMerge not found") sys.exit(1) diffmerge = validLocations oldhash = hashFile(base) # Works on Windows according to (IRC nick) Zephtar (orignial author) #cmd = '"%s" "%s" "%s" "%s"' % (diffmerge, local, base, other) # Works on OS X and Correct according to doc: # http://docs.python.org/library/subprocess.html#subprocess.Popen cmd = (diffmerge, local, base, other) p = subprocess.Popen(cmd) p.wait() newhash = hashFile(base) if oldhash == newhash: sys.exit(1) else: shutil.copyfile(base, local) sys.exit(0)