Reputation: 11270
We have a big Hg repo, hosted in a remote location. Performing an hg clone
from this master repo takes about an hour. What we generally do to speed things up is to hg serve
a local repo of a colleague, hg clone http://colleague-machine
, and then change de default
path in .hg/hgrc
to the address of the master repo.
This is all well and good, but this workaround has one drawback: because we are cloning the repo of a developer, some draft commits can be cloned along with the public ones. Moreover, these commits become public in the cloned repo, making them indistinguishable from the others.
One possibility I found is to make the developer's repo non publishing, in order to preserve the phases of the commits and to remove them later on. Another possibility is to create a bundle containing only the public commits, instead of cloning directly.
These methods are more complex to explain and to document. Is there an option for hg clone
to clone only the public commits? I tried with hg clone -r "public()"
, but clone does not take a revset, just a regular commit identifer. Alternatively, is there an option for hg serve
to serve only the public commits?
Upvotes: 3
Views: 202
Reputation: 11270
I ended up using a combination of hg serve
option and hg strip
.
On the existing repository:
hg serve --config phases.publish=False --port 0 --prefix repo-name
On the target machine:
hg clone <address printed by `hg serve`>
cd repo-name
hg strip -r "draft()"
The phases.publish=False
config makes the repo non-publishing, and thus preserves the phase of the commits that are cloned. Now that the phases are kept on the target machine, it is easy to strip them off after the clone.
Upvotes: 0
Reputation: 487755
Throw disk space at the problem: just keep a local mirror clone that you update regularly.
Cloning the "true master" is slow because it's far away over a slow link. But updating the mirror is fast because, while the true master is far away over a slow link, little data needs to traverse it; and cloning the mirror is fast, and gets you the state of the true master as of the last time the mirror was updated.
As you mention, you can then just replace the default
path (and maybe run a subsequent hg pull
to pick up anything not-yet-mirrored, if needed). Your new clone is then the same as it would have been, had you cloned from the far-away slow true master, except that it went fast.
Git has this kind of cloning built in, as what's called a reference clone. You point your git clone
process at two repositories: the true source, and the "close and fast" reference. It gets hash IDs from the true source but then uses the close-and-fast reference's storage for its data. You can then choose to continue to rely on the reference (default) or "dissociate" from the reference so that your clone is independent. It needs this dissociate operation because it can do a somewhat dangerous path-name-based "link" (not really a link in the sense of hard links; more an in-Git analogue to symbolic links) to the original, and does so by default here.
I don't think Mercurial has anything equivalent "out of the box". I imagine it should be relatively easy to write as an extension, though, if you are up for that sort of thing. You wouldn't need --dissociate
at all, it would be the default wherever hard links are not feasible.
Upvotes: 2
Reputation: 5580
One way to do this is to use hg clone -r <rev>
where <rev>
is public. That will ensure that you won't get any draft commits, although you will miss any branches that aren't ancestors of <rev>
.
I don't think there's a generic way to clone only public changes. It might be possible via a server-side extension or in-process hook though.
Upvotes: 1