Sharing One Mercurial Store Across Many Working Directories with hg share
hg share lets multiple Mercurial working directories read one .hg store. This architecture note covers the trust boundary, safe usage rules, failure modes, and when full clones are the better design.
01 Apr 2026, 17:03 UTC

The problem: multiple checkouts, one store
If you keep several working copies of the same Mercurial repository — one per feature branch, one for a stable build, one for experiments — a plain hg clone duplicates the entire .hg store each time. On a repository with years of history, that is gigabytes of identical revlog data copied per checkout, plus the cost of pulling changes into every clone separately.
The useful takeaway: hg share gives you independent working directories that all read from a single shared .hg store. You get per-checkout independence (different parents, different uncommitted changes, different branches checked out) without duplicating history. The trade-off is a strict trust boundary: only one repository owns the store, and history-rewriting operations belong there alone.
Requirements
This design fits when you need:
- Two or more working directories of the same project on one machine.
- Disk efficiency — history stored once, not once per checkout.
- Instant propagation: a commit made in any share is immediately visible to all others, because they read the same store. No pull required.
- Independent working-copy state: each share has its own checked-out revision, uncommitted changes, and working-copy parent.
It does not fit when each checkout must be relocatable, must survive deletion of the original repository, or must have its own remote configuration. Those cases need real clones.
The smallest suitable design
Create one base repository that owns the store, then attach shares to it:
# Run as your normal user, in a directory you own
hg init base
cd base
echo "hello" > a.txt
hg add a.txt
hg commit -m "initial"
cd ..
hg share base feature-x
hg share base releaseAfter this, feature-x/.hg is not a full store. It contains a sharedpath file pointing at base/.hg plus the per-checkout state (the dirstate tracking the working parent, and share-local files). All history — changelogs, manifests, file revlogs — lives only in base/.hg.
Verify the layout before relying on it:
# In feature-x/
hg root
hg paths
cat .hg/sharedpath # should point to ../base/.hgThen work normally in each share. hg update, hg commit, hg branch, and hg merge all behave as usual. A commit in feature-x appends to the shared store, so hg log in release shows it immediately — but the release working directory stays on its own parent until you explicitly update it. That separation of "shared history, private working copy" is the entire point.
Trust and data boundaries
There is exactly one writable, authoritative store: the base repository's .hg. Every share trusts it completely. This produces three rules:
- Never rewrite history in a share. Commands that mutate store structure or rewrite changesets —
hg strip,hg histedit,hg rebasein some configurations,hg convert-style operations — must run in the base repository, with all shares idle. Running them from a share risks corrupting the store every other share is reading. Depending on version, Mercurial may refuse or warn; do not treat that as a guarantee. - The base repository is a single point of failure. If
base/.hgis deleted or corrupted, every share becomes unusable. Back up the base store, not the shares. - One writer at a time. Mercurial uses lock files for store integrity, but a shared store is designed for a single user with multiple checkouts, not concurrent writers. Do not point multiple users or automated jobs that push at the same shared store; use a proper server-side repository for that.
Also note that shares inherit the base repository's path configuration. If you need a different default push target per checkout, shares are the wrong tool.
Operational checks
After setting up shares, confirm the design holds with these checks:
- Independence of working copies: in
feature-x, runhg updateto an older revision; inrelease, runhg summaryand confirm its parent is unchanged. - Shared history: commit in one share, then run
hg log -l 3in the other without pulling. The new changeset should appear. - Store location:
hg rootin a share prints the share's path, butcat .hg/sharedpathreveals where the data actually lives. Check this before running any destructive command.
Failure modes
- Moving the base repository. Shares reference the base by path. If you relocate
base, operations in the shares fail with missing-store errors. Fix by editing each share's.hg/sharedpathto the new location, or recreate the shares. - Deleting the base working directory. The shares keep pointing at the old store path. If you only deleted the working files but kept
base/.hg, shares still work; if the store went too, everything is gone. - History rewrite in a share. A strip executed against the shared store can leave other shares with dirstate pointing at changesets that no longer exist, producing "unknown revision" errors on the next update. Recovery generally means re-sharing from a repaired base.
- Concurrent access. Two processes committing through different shares at the same moment can interleave badly. Keep shared setups single-user.
When to change the design
Switch from shares to full clones when any of these become true: the checkouts must live on different machines or be moved independently; the base repository cannot be treated as permanent infrastructure; different remotes per checkout are required; or the project rewrites history frequently as part of normal workflow (heavy histedit/strip usage), which makes the single-writer rule hard to honor. In those cases the disk savings of sharing are not worth the fragility.
For the common case — one developer, one machine, several branches in flight — hg share is the minimal design that meets the requirements: one store, many working directories, and a clear rule about where destructive commands are allowed to run.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.