Convert repository to older version (without sparse revlog)

With 4.9, new repositories will be created using sparse-revlog by default. However existing repositories are untouched. They stay in the same format they have been created with.

Avoiding the issue at repository creation

To prevent the users who upgraded to create sparse-revlog repositories he needs to set the following in his user configuration (hg config -e)

[format]
sparse-revlog = no

Do you have global control of your users configuration?

Downgrading existing repositories

If you want to downgrade such newly created repository you do the following:

  1. add the following to the repository configuration (hg config -l)
[format]
sparse-revlog = no
  1. run hg debugupgraderepo --run (with 4.7 or newer)

Upgrading existing repositories

If you want to upgrade existing created repository, the process is similar:

  1. add the following to the repository configuration (hg config -l)
[format]
sparse-revlog = yes
  1. run hg debugupgraderepo --run (with 4.7 or newer)

Note: the page https://www.selenic.com/mercurial/hgrc.5.html#format is outdated. The website for mercurial have been https://www.mercurial-scm.org/ for a couple of years.


Normally it should be possible to instruct hg during a clone operation NOT to use a specific, newer repo format.

There are specific configuration options for this, as shown in the docs:

Config option: format

usegeneraldelta

Enable or disable the "generaldelta" repository format ... Enabled by default.

dotencode

Enable or disable the "dotencode" repository format ... Enabled by default.

usefncache

Enable or disable the "fncache" repository format ... Enabled by default.

usestore

Enable or disable the "store" repository format ... Enabled by default.

However for some reason there is no option listed corresponding to the newest repo format which as noted in the question is "sparse-revlog" (documented here).

But that seems to be just a documentation oversight, so similar to the answer to another question, you should be able to re-clone using a command similar to this:

hg clone --config format.sparse-revlog=no  <source> <dest>

This will require hg to NOT utilize that format, which means the older prior format should be what you get and will be compatible with your local hg clients.

Added info/explanation from a comment by Juan: this will work if (a) your clone source & destination are not on the same filesystem or (b) you add --pull.

(By default Mercurial will try to create hard links for speed & space savings. Avoiding hard links by cloning to different filesystems or different hosts altogether or by forcing the clone to not use hard links on the same filesystem by using --pull will allow the new repo to be created without sparse-revlog.)

I guess you would have to do this to replace every existing clone that has been pulled since the central repo was accidentally upgraded. I would plan that work carefully, to make sure no local changes are lost. You could to a local pull using the same config option to transfer commits from the old to new repos.


Here's one approach which is kind of ugly (understatement) but might work as a fix, since you only have to do it once...

This approach takes advantage of the fact that an HTTP-served HG instance can apparently interoperate between any internal repo versions.

According to docs Missing Requirement section Downgrade your repository over the network:

Because all versions of Mercurial can interoperate over the network, an old client can simply pull from a repository served by a new client:

# run this on the new client
$ hg serve
listening at http://hostname:8000/ (bound to *:8000)

# run this on the old client
$ hg clone http://hostname:8000/ downgraded-repo

Since you are not using hg serve already this obviously won't work for you automatically. But you might be able to use it temporarily. Something like this:

  1. Setup a temporary hg serve running on some PC. (Ideally, IT restrictions won't prevent this.) It should serve your central repo.

  2. Identify all clones of the repo which need to be fixed. (Maybe cull any which aren't needed to save work here.) These should only need to be ones modified (pushed/pulled) by a THG 4.9 client.

  3. Backup work. Ideally, commit and push everything possible first to reduce the later step which restores any backed-up files.

  4. Following the example above, re-clone from the temporary hg serve PC to new local clones in all instances where they are needed.

  5. Restore any backed-up work to the new clones (this is the worst part and could be really painful). I think this has to be done manually; maybe there is a clever diff/patch approach which would be easier.

  6. Shut down the temp hg serve instance

Be cautious that the problem could eventually re-propagate outwards. i.e., if even one repo is overlooked and later is used to push to the central repo, the problem will repeat itself.

Alternative / variation - you could run hg serve on each & every developer's PC that had used THG 4.9, and have them each independently re-clone from localhost. This might get around any IT limitations, if absolutely necessary. (But if you don't have IT limitations, it doesn't really matter where hg serve itself is running).


If you have a very large # of affected devs / clones, I am not sure this approach is best. For one thing, if you were able to involve your IT people to upgrade everyone to the newest hg version, it could be a much easier fix overall.