Hg Guest Repo

Extension for enterprises needing to handle modules and components

Use case:

  • Many products, multiple projects within those products, multiple developers within those projects, multiple branches per developer

  • Source code shared in a multiplicity of configurations

  • Third party code (possibly patched on some branches)

  • A given module may have multiple versions going into the same product

Hg subrepos do not handle the sharing of components well, due to the recursive merge from the top (super) repo and requirement to lock at a specific version.

Guestrepo's goal is to overcome these limitations.

The guestrepo extension does not change any existing Mercurial behavior. It only adds new commands.


Guest repositories are administered using the two files .hgguestrepo and .hggrmapping. These files are in the INI format used by Mercurial.

Remote Paths

Each guest repository must have a remote path defined in the .hggrmapping file to successfully push or pull. Remote paths are referenced by assigning a each path a unique name. The .hggrmapping file lists remote paths in the following INI format:

name = remote-path

If a remote repository is moved, the path referenced by a name can be updated to point to the new location.

Example .hggrmapping file:

remoteid  = http://host/path/to/repo
remoteid2 = /path/to/repo2

The .hggrmapping file used for any operation is the .hggrmapping file at the most recently committed head of the current branch. Using the most recent revision of the .hggrmapping file keeps the guests of previous revisions pointed to the correct location.

The --local flag causes the .hggrmapping file in the working directory to be used.


The .hgguestrepo file defines guests by specifying three things:

  • location: The location of the guest relative to the root of the parent repository.
  • remote id: The name of a remote path defined in the .hggrmapping file.
  • changeset id: A Mercurial identifier e.g., a tag, bookmark, changeset hash, branch, or other future identifier resolvable to a single changeset.

The .hgguestrepo file lists guest repositories in the following INI format:

location = remote-id changeset-id

Example .hgguestrepo file:

path/to/guest = remoteid csid
path/to/other/guest = remoteid2 csid

If the the directory of the guest repository exists, it must contain a mercurial repository.



hg grpull [guestrepo...]

Pull each guest repo from the location specified in the mapping file. If any guest repo does not exist it is cloned and updated to the specified changeset id in the .hgguestrepo file. See sync for information on how guests are updated. A pull to an existing repo will not update.

Pull is run recursively on guest repositories.


hg grpush [guestrepo...]

Push each guest to the path specified in the mapping file.

Push is run recursively on guest repositories.


hg grsync [guestrepo...]

Update each guest repo to the changeset identifier in the .hgguestrepo file. The changeset identifier can be a branch, tag, changeset hex, bookmark, or any other identifier that can be given to Mercurial's update command.

A warning will be raised if a guest is updated to a branch with multiple heads.

Sync is recursive. If the update operation adds a new guest, it is cloned to the newly added identifier.

Sync will present an error and do nothing if there are local changes in any guest repository. This prevents the update from causing a merge with local changes.


hg grfreeze

The freeze command outputs the state of the guest repositories to the .hgguestrepo file. It uses same format as the .hgguestrepo file, but only outputs the absolute changeset hash.

"local_dir" remoteid "changeset hash"

Freeze can be used to generate an .hgguestrepo file for a release:

$ hg branch Release
$ hg grfreeze
$ hg commit -m Release


hg grstate

Print the exact changeset of all guests to stdout, as in .hgguestrepo.

The state command outputs the state of the guest repositories to standard out. It uses same format as the .hgguestrepo file, but only outputs the absolute changeset hash

State is essentially the freeze command directed to standard out rather than .hgguestrepo.


hg grsummary

Summary presents a simple description of the state of the project: a column of subdirectories, followed by the branch of the current changeset, followed by the tags and bookmarks pointing to the current changeset, followed by a * if modified.

local_directory (branch) [tags] [bookmarks] [*current bookmark] [*]

Error Handling

One of the key defects in the user experience of subrepositories is the invalid state that is occasionally maneuvered into and the requirement for a guru to fix the user's state. This wastes time. We claim it is better to have a globally inconsistent repository with the ability to return to a consistent state than a globally consistent and dysfunctional repository.

Errors parsing configuration files and resolving remote paths will cause guestrepo to abort before attempting any operations.

Errors that occur when operating on a guest repository do not cause other operations to be aborted. At the end of operation all errors are reported along with the current state of the repository and if it is 'sane' to use (i.e., not left in an an aborted operation state).

Errors will be displayed on standard error, and all errors cause a non-zero exit code.


The guestrepo extension has an option to use multiple threads to improve performance in I/O bound situations.

Unresponsive remote operations may cause guestrpo to hang indefinitely.


  • Changeset identifiers in the .hgguestrepo file cannot contain spaces
  • Sync is a terrible name for the update command
  • Sync aborts if the working copy of .hgguestrepo is modified
  • Missing commands for incoming and outgoing
  • Convert script could be improved to allow both guestrepos and subrepos
  • Summary complains too loudly about missing guest repos
  • No warning on modified/uncommited guestrepo files


Guestrepo: A Mercurial Extension for the managing of components

Copyright (C) 2012 Schweitzer Engineering Laboratories, Inc.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

Contact information:

Schweitzer Engineering Laboratories, Inc. 2350 NE Hopkins Court Pullman, WA 99163 - USA

Contributors: Ben Smith