Moving from CVS to Mercurial

Yesterday, Venkman moved from CVS to Hg. For the benefit of others who may want to move other extensions, here is a rough attempt to outline the steps I took.

First, some notes of caution:

  • HG uses a character encoding specific to your machine. For my mac, that turned out to be mac-roman. You usually don’t want that, and need to tell it you want it to use utf8 instead. I could actually not convince it to do this for the author map – it stored the authors in mac-roman anyway. Check your imports carefully.
  • HG’s default ConvertExtension is your friend, as long as you tell it what to do the right way.
  • You probably want to create a test repo (I ended up using several, in trial and error!) at Instructions for doing that may be found here. Keep in mind that once you stick something in a Mercurial repo, it will be there forever. This means anyone pulling from your repo will have to keep downloading all those files. Be careful about what you push to the repo, because once you’ve pushed something there’s no going back (short of asking IT to delete the repo and trying again).

Alright. Down to the actual import. Here is the actual steps I ended up following. When I say “ended up” I mean “after trying N different things which didn’t work”, where N was large enough to keep me busy for a fair number of hours.

  1. Check out the relevant code from CVS. In my case, this meant:
    cvs -d co mozilla/extensions/venkman
  2. Enable the convert and mq extensions. Edit your ~/.hgrc file and include:
    mq =
  3. Decide whether you want all the branches in CVS. If, like me, you’re importing an extension, you probably don’t care about the Firefox/Mozilla release branches. You just want trunk history. In order to do this, we ask the convert extension to split up branches. Edit your ~/.hgrc file and include:
  4. Now you can run convert, more or less like this:
    hg --encoding utf8 convert vnkCVS/mozilla/extensions/venkman venkman-initial
  5. Inspect your handiwork: you will now end up with several directories, one for each branch. You presumably want “default”, which should correspond to trunk. We will convert from hg to hg in a bit, to obtain just that.  Go back to your ~/.hgrc file and remove the [convert] section you added in step 3. This way, the new repo we’ll convert to won’t still have the “default” directory.
  6. Additionally, we still need to map authors. CVS used something like: “”, and in Mercurial, we expect something of the form “John Doe <>”. So we need to define an author map file, in which each line simply maps one set of authors to the next. For example: = John Doe <> . I uploaded the Author map for Venkman CVS to hg import that I used. It probably does not cover everyone who committed to your repo. If there are aliases that you’re not familiar with (Mozilla CVS is pretty old!) then Google and asking on IRC are easy ways of figuring out who’s who. To create a complete author map, I used some ad-hoc sed magic on:

    hg log | grep "user:" > foo.txt
  7. You may want to unify the entries of committers who have committed using different committer IDs. Ohloh can help there.
  8. Run hg convert again:
    hg --encoding utf8 convert --authors myAuthorMap.txt venkman-initial/default/ venkman-final/
  9. Check hg log. If there are loads of tags in which you’re not interested, you can use the hg strip command to strip the last hg revision, which added all the tags.
  10. Verify everything worked. Then add the correct “default-push” line to the .hg/hgrc file for the new repo you created, and push to your user repo. Check that everything is correct by reviewing the hgweb overview of things. If so, change the default-push line to point to the “real” repo, and push all the changesets there. You’re done!

This may not be the easiest or best way to do things, but that’s the way I managed – suggestions/improvements appreciated!

6 thoughts on “Moving from CVS to Mercurial

  1. Ian: Because Firefox, Thunderbird, SeaMonkey, and a whole load of other Mozilla projects moved to Mercurial, so it would make no sense to move to something else (except perhaps SVN if we somehow had reasons not to use distributed version control, or something). It would only have complicated matters if we had moved to Bazaar or git, when what we’re trying to do is simplify things (in particular for localisers and for the SeaMonkey project).

  2. very good article in cvs->hg. I used to convert cvs->git via git cvsimport/cvsps but it’s not very reliable.

  3. abgalphabet:

    I’m not sure, I wasn’t interested in tags. From the steps, did you by any chance use hg strip to remove the revision that added all the tags? That would explain it. 🙂

    Otherwise, you may want to not use the bits about splitting out all the CVS branches (usebranchnames), and see where that gets you. I am by no means an expert on cvs->hg, but simply wrote these steps down in an effort to share what worked for me. If you have issues with these steps, I think the HG mailing lists, fora, newsgroups or IRC channels might be your best bet to get help to get it to do exactly what you want. Also look at the official wiki pages for the ConvertExtension (linked above).

Comments are closed.