How to convert


- Get a fresh clone of hgsubversion (from
  and also install its dependencies (e.g. subvertpy)

- Enable hgsubversion by adding it to the "[extensions]" section in your .hgrc.

- Enable the "hg shrink" extension by adding
    shrink = path/to/mercurial-source-tree/contrib/
  to the "[extensions]" section in your .hgrc.  It is also recommended that you
  apply the patch that is inside (it only modifies


- You should have a local copy of the Python SVN repo in the "python-svn"
  subdirectory of this working copy.  The recommended way is to "svnadmin load"
  the results of an "svnadmin dump" done on the server (once you have a dump,
  you can create further incremental dumps and load them in your copy).


- Run "./". This will mirror the "python-svn" SVN repo in a "python-hg"
  Mercurial repo.  The full conversion takes several hours, but you can stop it
  before the end if you like, and then do "hg pull" inside "python-hg" to
  resume converting.  "hg pull" should also allow you to add new SVN changesets
  when you have loaded an incremental dump into your "python-svn" repo.

- Inside, "python-hg", prepare a bundle of the branches needed for the "work
  repository" (a subset of the full converted repo containing only active
  dev branches and main maintenance branches):

    $ hg bundle --base null \
        -r default -r 3.2 -r 3.1 -r 3.0 \
        -r legacy-trunk -r 2.7 -r 2.6 -r 2.5 -r 2.4 \
        -r 2.3 -r 2.2 -r 2.1 -r 2.0 \

- Create the work repository:

    $ cd ..
    $ hg init work
    $ cd work
    $ hg unbundle ../work.bundle

- It is then recommended to shrink the work repo and the full history repo.
  See's docstring for indications.  You should do the shrinking
  in a separate clone, in case it gets corrupted (you don't want to convert
  again from scratch).
  A shrunk work repository should contain 8 branches (all non-closed),
  7 heads (all non-closed), and weigh around 170MB (I'm talking about the ".hg"

  Don't hesitate to inspect the results of the following commands:

    $ hg branches -c   # displays all branches, including closed
    $ hg heads -c      # displays all heads, inclusing closed
    $ du -hs .hg       # displays on-disk repo size

  Also, the size of a full bundle gives (IIUC) an approximation of the
  amount of bytes transfered over the network when doing a remote clone:

    $ hg bundle -a cpython.bundle

- Setup hooks and on other configuration on the public repository's .hg/hgrc:

    description = CPython repository
    contact =

    # Needed for the hook to work, otherwise it will be a no-op
    eol =


    # Uses our modified version of (see
    pretxnchangegroup.eol = python:hgext.eol.allcsethook
    # Enforce whitespace rules for all new head(s)
    pretxnchangegroup.checkwhitespace = python:/data/hg/repos/hooks/
    # Reject new changesets on closed branches, or brand-new branches
    pretxnchangegroup.checkbranch = python:/data/hg/repos/hooks/
    # Reject multiple heads per branch
    pretxnchangegroup.checkheads = python:/data/hg/repos/hooks/

    incoming.notify = python:/data/hg/repos/hooks/
    #incoming.sphinxbuild = hg up; sh -c 'source /data/hg/sphinx-env/bin/activate; sphinx-build -q . /data/'

    notify =

How to recreate a feature repo from a feature branch?

Let's say the feature branch is 'pep-3151'.

- Get the last corresponding changeset id from the revision map (here "cpython"
  is a local clone of the main repository):

    $ grep pep-3151 cpython/Misc/svnmap.txt |tail -n1
    88675 728fbc26359c107ff755ce5bb6b9b3b080f1bef1 pep-3151

- Clone the full history up to that changeset into a new repository:

    $ hg clone -r 728fbc26359c107ff755ce5bb6b9b3b080f1bef1 \ pep-3151
    $ cd pep-3151

- Get the last svnmerge'd revision from the commit message:

    $ hg log -r 728fbc26359c107ff755ce5bb6b9b3b080f1bef1
    changeset:   44201:728fbc26359c
    user:        Antoine Pitrou <>
    date:        Mon Feb 28 18:08:07 2011 +0000
    summary:     Merged revisions 88633,88636,88639-88640,88643-88647,88650,88652-88654,88656,88658,88660,88663-88664,88668,88671 via svnmerge from

  So, here, it's 88671.

- Get its corresponding changeset id:

    $ grep ^88671 ../cpython/Misc/svnmap.txt
    88671 2f07d375ce6eecab471e5d8ebb889106f169da10 py3k

- Pull that changeset too:

    $ hg pull -r 2f07d375ce6eecab471e5d8ebb889106f169da10 ../cpython

- Update to the feature changeset, and merge with the other:

    $ hg update 728fbc26359c107ff755ce5bb6b9b3b080f1bef1
    $ hg merge 2f07d375ce6eecab471e5d8ebb889106f169da10

- Revert all files to the feature changeset and resolve "conflicts":

    $ hg revert -a -r 728fbc26359c107ff755ce5bb6b9b3b080f1bef1
    $ hg resolve -am

- Commit the merge:

    $ hg ci -m "Merge feature branch pep-3151 with its ancestor"

The repo is now ready for further work (and should probably be published
online).  It still needs pulling younger changesets on the main line of
development, if you want to merge further.