I don't use Mercurial, but i'd like to start, so i'm reading about it. The only SCM system i've used extensively is CVS. Most of what i've read about Mercurial makes sense, and sounds good. But i'm alternately shocked and perplexed by that way it does tags.
A tag is just a nickname for a changeset (and by 'changeset' we really mean the state resulting from the changeset). Cool. The mapping from tags to changeset IDs is stored in the .hgtags
file. Also cool. The .hgtags
file is versioned.
What?
This has lots of counterintuitive consequences. For instance, if i commit a changeset which i then want to tag (say, the code which will form release 1.0), i have to commit again after tagging, to put the updated tag file into the repository. And if i then update to that tagged changeset at some later date, the working copy won't contain any knowledge of that tag. If i do some work, thus founding a new branch (say, for bugfixes, heading towards 1.1), that branch won't have any knowledge of the tag from which it grew. Unless i copy it over manually, that is.
And as development continues both on the original trunk and my new branch, with tags being created to mark important changesets (the 2.0 release on the trunk, the 1.1 and 1.2 bugfix releases on the branch), both branches will proceed in ignorance of the other branch's tags. So, if i finish working on one branch, and want to switch to some particular changeset on another (say, i finish the 1.2 bugfix release, but now have to start on the 2.1 bugfix, based on 2.0), i am now stuffed. My current changeset doesn't know about 2.0!
What can i do?
- I can ask someone who's working on the 2.x branch to read out the actual changeset ID for 2.0, and use that explicitly, but this is appalling.
- I could name my branches, as well as using tags, so that i could hop across to the head of the 2.x branch, thus learning about the new tags, and then skip back to the 2.0 tag. Assuming that branches, unlike tags, are universally visible - is that the case? Even if it is, this seems clunky.
- I could maintain a single global
hgtags
file outside the repository, and use a couple of hooks to pull in a copy on an update, overwriting the local copy, and to copy back any changes on a commit. I'm not sure how this would work in a multi-user environment, where developers are pushing changes to a shared repository; i might need a separate repository just for thehgtags
file. - I could use local tags, which stand outside the versioning mechanism, and so avoid the whole problem. As with shared global tags, i would have to put in place a mechanism to synchronise the
localtags
file between developers.
None of these solutions seem totally great. What should i do?
An assumption here is that i'm managing branches using named branches in a single repository, rather than repository-per-branch. Would the situation be any better if i did the latter?