''This page describes Mercurial 0.9.5 and older releases and is no longer relevant for Mercurial 1.0'' Before Mercurial 1.0, a script named '''hgmerge''' was installed by default. As of Mercurial 1.0, hgmerge is no longer installed (and it should not be distributed with Mercurial), but hg still uses it, if it's present on the system and no other merge tools are configured. See [[MergeToolConfiguration]] for the new mechanism. The hgmerge script tries to invoke several merge programs in turn. If it cannot find any of them, hgmerge runs a text editor on a version of the file with the conflicts annotated. The merge program is defined in .hgrc with {{{ [ui] merge = your-merge-program }}} Note that the order of the argument can differ between hg and your merge program, hgmerge is called {{{ hgmerge local base other }}} The files have to be merged into `local`. For example kdiff3 is called {{{ kdiff3 base local other -o output }}} === Python merge script === There is a python based [[http://hg.borho.org/hgmerge/raw-file/tip/hgmerge.py|merge]] script available which will detect the merge tools you have available on your computer and use them appropriately (similar to the hgmerge shell script which is packaged with Mercurial). Since it's written in python it is portable to all the platforms that run Mercurial. On Windows, the script will even look in the registry for tools which are installed but not in the system path (Note: registry searching requires the [[https://sourceforge.net/projects/pywin32/|pywin32]] package). To use this merge script on a *nix system, simply copy the script somewhere in your path, make it executable, then add these lines to your ~/.hgrc: {{{ ; Unix/Linux ~/.hgrc example [ui] merge = hgmerge.py [hgmerge] interactive = kdiff3 noninteractive = diff3 }}} Configuration of the script is now [[http://qct.wiki.sourceforge.net/HgMerge|documented]] separately. On Windows, you will have to specify {{{merge = python \path\to\hgmerge.py}}} in the {{{[ui]}}} of your Mercurial.ini, presuming you have a python interpreter installed on your computer. If you have no python interpreter, then either [[http://www.python.org/download/|install one]] or else you might be interested in trying the more user-friendly front end to Hg, [[http://tortoisehg.sourceforge.net/|TortoiseHg]] instead. {{{ ; Windows c:\Documents and Settings\USERNAME\Mercurial.ini or %HOME%\Mercurial.ini example [ui] merge = python c:\Mercurial\hgmerge.py [hgmerge] interactive = kdiff3 noninteractive = diff3 }}} For this to work, the programs python.exe, kdiff3.exe, and diff3.exe are assumed to be on your PATH. See above for links to obtain various merge programs like kdiff3 or diff3. It also assumes you've saved the [[http://hg.borho.org/hgmerge/raw-file/tip/hgmerge.py|hgmerge.py]] file to c:\Mercurial\ . === Windows === On Windows you can create a batch file called hgmerge.cmd which is located somewhere in the path, e.g. in C:\Program Files\Mercurial. In this case do not set the {{{merge}}} entry in the {{{ui}}} section of your hgrc file. Having the batch file is enough. Note that you must create something, as no hgmerge script is currently provided on Windows. The scripts are not intended for the user: If you call them directly they will exit your command prompt. This is necessary to make hg detect failed merges. If you really want to call this script, use "cmd /c hgmerge" or "start hgmerge". ==== KDiff3 ==== Example script for KDiff3 (works with XP and later versions): {{{ @echo off setlocal :: Look in the registry for KDiff3 location for /f "skip=2 tokens=3*" %%A in ( '"reg query "HKEY_CURRENT_USER\SOFTWARE\KDiff3" /ve 2> nul"' ) do set KDiff3Path=%%B if "%KDiff3Path%"=="" (goto :notfound) else (goto :kdiff3) :kdiff3 "%KDiff3Path%\kdiff3.exe" --auto --L1 Base --L2 Local --L3 Other %2 %1 %3 -o %1 if %errorlevel% neq 0 (exit 1) else (exit 0) :notfound echo hgmerge: cannot find KDiff3 location in the registry. exit 1 }}} Note: this script has problems when whitespace present in kdiff3 path. For example I have kdiff3 installed in C:\Program Files\KDiff3\. Until someone fix the script to determine path correctly in such case, we may just hardcode full kdiff3 path in the script instead of querying registry: {{{ @echo off "C:\Program Files\KDiff3\kdiff3.exe" --auto --L1 Base --L2 Local --L3 Other %2 %1 %3 -o %1 if %errorlevel% neq 0 (exit 1) else (exit 0) }}} ==== TortoiseMerge ==== Example script for Tortoise``Merge (works with XP and later versions): {{{ @echo off setlocal :: Look in the registry for TortoiseMerge location for /f "skip=2 tokens=2*" %%A in ( '"reg query "HKEY_LOCAL_MACHINE\SOFTWARE\TortoiseSVN" /v TMergePath 2> nul"' ) do set TMergePath=%%B if "%TMergePath%"=="" (goto :notfound) else (goto :tortoisemerge) :tortoisemerge "%TMergePath%" /base:%2 /mine:%1 /theirs:%3 /merged:%1 if %errorlevel% neq 0 (exit 1) else (exit 0) :notfound echo hgmerge: cannot find TortoiseMerge location in the registry. exit 1 }}} In order to get it to TortoiseMerge to work with Cygwin's version of Mercurial try this: {{{ @echo off setlocal :: Look in the registry for TortoiseMerge location for /f "skip=2 tokens=2*" %%A in ( '"reg query "HKEY_LOCAL_MACHINE\SOFTWARE\TortoiseSVN" /v TMergePath 2> nul"' ) do set TMergePath=%%B if "%TMergePath%"=="" (goto :notfound) else (goto :tortoisemerge) :tortoisemerge for /f "tokens=1 delims=" %%A in ( '"cygpath -w %1"' ) do set TMergePath1=%%A for /f "tokens=1 delims=" %%A in ( '"cygpath -w %2"' ) do set TMergePath2=%%A for /f "tokens=1 delims=" %%A in ( '"cygpath -w %3"' ) do set TMergePath3=%%A echo %TMergePath1% "%TMergePath%" /base:"%TMergePath2%" /mine:"%TMergePath1%" /theirs:"%TMergePath3%" /merged:"%TMergePath1%" if %errorlevel% neq 0 (exit 1) else (exit 0) :notfound echo hgmerge: cannot find TortoiseMerge location in the registry. exit 1 }}} ==== WinMerge ==== Example script for Win``Merge (works with XP and later versions): {{{ @echo off setlocal :: Look in the registry for WinMerge location for /f "skip=2 tokens=2*" %%A in ( '"reg query "HKEY_CURRENT_USER\Software\Thingamahoochie\WinMerge" /v Executable 2> nul"' ) do set WMergePath=%%B if "%WMergePath%"=="" (goto :notfound) else (goto :merge) :merge "%WMergePath%" /e /ub /wl /dl "Repository" %3 %1 if %errorlevel% neq 0 (exit 1) else (exit 0) :notfound echo hgmerge: cannot find WinMerge location in the registry. exit 1 }}} ==== Variation ==== A variation on each of the above scripts is to just try to launch the merge program using the default search path. For example the KDiff3 batch file might be modified to look something like this. {{{ @echo off setlocal :: Look in the registry for KDiff3 location for /f "skip=2 tokens=3*" %%A in ( '"reg query "HKEY_CURRENT_USER\SOFTWARE\KDiff3" /ve 2> nul"' ) do set KDiff3Path=%%B if "%KDiff3Path%"=="" (goto :trydefaultsearchpath) else (goto :kdiff3) :kdiff3 "%KDiff3Path%\kdiff3.exe" --auto --L1 Base --L2 Local --L3 Other %2 %1 %3 -o %1 if %errorlevel% neq 0 (exit 1) else (exit 0) :trydefaultsearchpath kdiff3.exe --auto --L1 Base --L2 Local --L3 Other %2 %1 %3 -o %1 if %errorlevel% neq 0 (exit 1) else (exit 0) }}} ==== DiffMerge ==== Example script for DiffMerge (works on any Windows system with [[http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx|Windows PowerShell]] installed): {{{ param($localPath, $basePath, $otherPath); $windowTitle = "Mercurial Merge"; $localTitle = "Mine"; $baseTitle = "Base"; $otherTitle = "Theirs"; $diffMergePath = "C:\\Program Files\\SourceGear\\DiffMerge\\DiffMerge.exe"; if (-not [System.IO.File]::Exists($diffMergePath)) { Write-Host [System.String]::Format( "DiffMerge not found: {0}", $diffMergePath); return 1; } if (-not [System.IO.File]::Exists($localPath)) { Write-Host ("Local file not found: {0}", $localPath); return 1; } if (-not [System.IO.File]::Exists($basePath)) { Write-Host [System.String]::Format("Base file not found: {0}", $basePath); return 1; } if (-not [System.IO.File]::Exists($otherPath)) { Write-Host [System.String]::Format("Other file not found: {0}", $otherPath); return 1; } $diffMergeProcessStartInfo = New-Object System.Diagnostics.ProcessStartInfo; $diffMergeProcessStartInfo.FileName = $diffMergePath; $diffMergeProcessStartInfo.Arguments = [System.String]::Format( '--nosplash --merge --caption="{0}" ' + '--title1="{1}" ' + '--title2="{2}" ' + '--title3="{3}" ' + '{4} {5} {6}', $windowTitle, $baseTitle, $localTitle, $otherTitle, $basePath, $localPath, $otherPath); $diffMergeProcess = New-Object System.Diagnostics.Process; $diffMergeProcess.StartInfo = $diffMergeProcessStartInfo; $beforeMergeLastWriteTime = [System.IO.File]::GetLastWriteTime($localPath); $exitCode = $diffMergeProcess.Start(); $diffMergeProcess.WaitForExit(); trap [System.Exception] { Write-Host [System.String]::Format( "An error occured while starting DiffMerge.") return 1; } $afterMergeLastWriteTime = [System.IO.File]::GetLastWriteTime($localPath); if ($afterMergeLastWriteTime -le $beforeMergeLastWriteTime) { Write-Host "File not changed."; return 1; } else { return 0; } }}}