Prevent multiple heads when pushing to a Mercurial repository

 · Jean Schurger
Table of contents

Mercurial heads and push -f

Mercurial is a fascinating tool but when several people work on the same project, dealing with 'heads' can quickly become a nightmare.

You know, you want to push your last super-fantastic commits to give them to the world, and Mercurial barks:

"push creates new remote head"

So, you push using the '-f' hoping that it will not be too hard to merge later… mistake ! Think before, push after.

The following little hook, configured on the remote repository will prevent you to accidentally ignore the merge question while you're under the enthusiasm effect of your last creation.

#!/usr/bin/env python

"""
[hooks]
pretxnchangegroup.forbid_multiple_heads = forbid_multiple_heads.py
"""

import sys
import os
from mercurial import hg, ui
uiface = ui.ui()
from collections import Counter
repo = hg.repository(uiface, os.environ['PWD'])
branches = Counter([repo.changectx(head).branch()
                    for head in repo.heads()
                    if repo.changectx(head).changeset()[5].get(
                    'close') != '1'])
bad_branches = filter(lambda branch: branches.get(branch) > 0, branches)
for branch in bad_branches:
    sys.stderr.write("Pushing would create too many heads "
                     "(%s) for branch '%s'.\n" % (branches.get(branch), branch))
if bad_branches:
    sys.exit(1)