Automatically close merged branches in mercurial

@echo off

:: :: ::
:: This script can be run by hand or added as a hook to mercurial (.hg/hgrc):
::      [hooks]
::      changegroup.closemerged = c:\scriptdirectory\closemerged.bat PROD c:\repo\projectdirectory
:: :: ::
:: Usage:
::  closemerged.bat MAINBRANCH PROJECTDIRECTORY
:: :: ::

set MAIN=%1

cd %2

echo Searching for not closed branches that were merged to %MAIN%...
hg log -r "head()-closed()-branch(%MAIN%)-branch(TEST)" --template "{branch}," > tmpFile
set /p BRANCHES=<tmpFile
del tmpFile

echo Processing branches: %BRANCHES%
call :parse "%BRANCHES%"
goto :end


:parse
setlocal
set list=%1
set list=%list:"=%
FOR /f "tokens=1* delims=," %%a IN ("%list%") DO (
  if not "%%a" == "" call :sub %%a
  if not "%%b" == "" call :parse "%%b"
)
endlocal
exit /b

:sub
setlocal
echo Querying %1
:: get last revision of branch
hg log -r "%1" --template {node} > tmpFileB1
:: get revision of ancestor of main branch and queried branch
hg log -r "ancestor('%MAIN%','%1')" --template {node} > tmpFileB2
set /p b1=<tmpFileB1
set /p b2=<tmpFileB2
del tmpFileB1
del tmpFileB2
:: if revision nodes are the same it means that branches are merged
if "%b1%"=="%b2%" call :close %1
endlocal
exit /b

:close
setlocal
echo Closing %1
hg update --clean %1
hg ci --close-branch -m "Closing merged branch."
endlocal
exit /b

:end
echo Updating to %MAIN% branch
hg update --clean %MAIN%

Mercurial log with one-liners

hg log --template '{node|short} | {date|isodatesec} | {author|user}@{branch}: {desc|strip|firstline}\n'

Once you have a nice template for one-line summaries of changesets, you can add a command alias in your ~/.hgrc file like this:

[alias]
shortlog = log --template '{node|short} | {date|isodatesec} | {author|user}@{branch}: {desc|strip|firstline}\n'

With the alias installed you can now type hg shortlog.

via Mercurial log with one-liners

Mercurial hooks

Useful Mercurial Hooks

Add/document commit-hook

To close the branch retroactively, just update to it and close it. You can also do so in bulk if you need to:

for b in `hg heads --template '{branches}\n'`; do \
    tip=`hg log -r $b --template '{node}'`; \
    anc=`hg debuganc $b default | cut -d: -f2`; \
    if [ $tip = $anc ]; then \
      echo $b merged; \
      hg up $b; \
      hg ci --close-branch -m 'Closing merged branch.'; \
    else \
      echo $b unmerged; \
    fi; \
  done

via Using a named branch

hg log -r 'head()-parents(merge())-closed()' --template '{branch}\n'

via hg hook to detect unmerged changesets