可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
As the definite guide aptly points out (search for "Tags and cloning"):
When you run hg clone -r foo
to clone a repository as of tag foo
, the new
clone will not contain any revision newer than the one the tag refers to,
including the revision where the tag was created. The result is that you'll
get exactly the right subset of the project's history in the new
repository, but not the tag you might have expected.
It means hg tags
in your new clone does NOT show the foo
tag. Same thing happens if you had cloned before foo
tag was added, and you do hg pull -r foo
.
(Digression: tag is about the only thing I don't quite get in hg. I understand there are advantages (e.g. merge) in putting it in a changeset, but it always feels weird to have meta data mixed with source code.)
It should be obvious that I'm asking for an automated way, instead of pulling the tag changeset as a separate manual step.
I know I could check for this scenario in an incoming
hook (so it works for both clone and pull), or wrap clone
and pull
.
But is there a better/easier way?
UPDATE hg bug tracker already has this issue.
回答1:
You want a giant hack with bash
and an embedded Perl script? Well, here it is...
#!/bin/bash
if [[ "$1" == "" || "$2" == "" || "$3" == "" ]]; then
echo 'hgclonetag <src> <tgt> <tag>'
exit 1;
fi
REV=`hg log -R $1 --rev $3: --limit=2 | perl -F: -lane 'if (/:([\dA-Fa-f]+)$/) {print $F[2] if defined($flag);$flag=1;}'`
hg clone --rev $REV $1 $2
This invokes the hg log
command to extract the revision number after the first tag-related revision and then clones to this revision.
Currently this does not work on remote repos: -R
switch only works on local repos unfortunately.
回答2:
The more I think about it the more I'm convinced the right answer is to just clone everything and update to the tag, which can be done in a single step:
hg clone http://host/path#tagname
That gets you everything and then does hg update
to tagname which sets your working directory to the correct revision. Given delta compression that's not necessarily much larger, and if it is you can automate cloning the bulk of it from a previous local clone.
回答3:
There is a postclone hook. It's called post-clone
(the hgrc manpage shows a post-ANYCOMMAND
and pre-ANYCOMMAND
exist) though as you pointed out you could also use *changegroup
or update
hooks too, since clone uses both of those functions (unless you suppress update with -U
).
What about just adding a --localtag
so you have the name but not the extra changeset if you need it for reference only. Something like
hg clone -r tagname URL
hg tag --local tagname
which you could easily build into a shell alias.
Other than that there's not necessarily guaranteed to be a way to have revision X and the revision where revision X is tagged without also having other revisions you don't want since the tag could have been applied after other work was done. You can, of course, always update to 'X' and to have subsequent changesets in you working dir, but they'll still be in your repo.
Honestly, once I figured out that the tag name doesn't come a long when you clone up to a tag, which I admit confused the heck out of me at first, I didn't find any need to bring along the changeset with the tag in it.
回答4:
Yes it can be done by post-clone/pull hooks, but there are a couple of crooks.
First, it only works for local repo, since you can't get the list of tags in a remote repo.
Second, dealing with clone/pull arguments and options is not trivial. (For clone I need to get the target repo, -r
, -u
, -U
. For pull I need -r
and -u
.) I tried to use fancyopts, but it can't deal with global options, which are processed away in dispatch. I managed to hack dispatch to give me only the args and opts of a command, but it feels and looks ugly.
Using command wrapper would eliminate the second problem.
I hope one day hg will add an option to clone and pull to do it cleanly.