Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I always know about all tags in Mercurial?

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 the hgtags 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?

like image 320
Tom Anderson Avatar asked Jun 06 '09 22:06

Tom Anderson


People also ask

How to tag a changeset in Mercurial?

Thus Mercurial stores tags as a file in the working dir. This file is called . hgtags and consists of a list of changeset IDs and their corresponding tags. To add a tag to the system, simply add a line to this file and then commit it for it to take effect.

How to remove tag in hg?

If you want to remove a tag that you no longer want, use hg tag --remove . You can also modify a tag at any time, so that it identifies a different revision, by simply issuing a new hg tag command. You'll have to use the -f option to tell Mercurial that you really want to update the tag.

How can I change branch in Mercurial?

In the Status bar, click the Mercurial Branch widget to open the Branches popup. Select the branch or bookmark to which you want to switch and in the menu that opens, click Update.

How do I create a branch in Mercurial?

Creating a branch Branching can happen by committing a changeset within a single repository or by committing diverging changes in distinct (but related) repositories. Two repositories are said to be related if they were once cloned from the same repository but later may have diverged.


2 Answers

Versioning the .hgtags file allows you to

  • edit tags and see who edited them (and why if they left a proper commit message)
  • transfer tags between repositories using the normal mechanisms

However, there are some confusion going on here.

  • You write that

    [...] And if i then update to that tagged changeset at some later date, the working copy won't contain any knowledge of that tag. [...]

    That is wrong, tags are collected from the .hgtags files found in all heads. That means that you can update to an old tag (hg update 0.1) and still see all your tags (hg tags).

  • You ask if branches are universally visible. Yes they are -- the names of named branches can be used in any context where you need to specify a changeset, as can tags.

Make sure you understand what named branches are before you begin using them. They are actually not necessary for making a bugfix branch. You can instead choose to simply go back (hg update 1.0) and fix the bug and then commit. That will create a new head, which your line of development towards 1.1 (this gives you multiple heads). So you don't have to create a named branch to add a new branch of development to your repository.

Having multiple heads is completely equivalent to having multiple clones. You can even convert back and forth: you can use

% hg clone -r X-head repo repo-X

to untangle the X-head changeset and its ancestors from the other changesets in repo. And you can combine multiple clones by simply pulling all changesets into one big clone.

Named branches are similar, yet different. They allow you to embed a named in each changeset. So you can have several changesets in your history with the name "foo". When you do hg update foo you will end up at the tip-most of these changesets. In this way, named branches function as a kind of floating tag.

If you are uncomfortable with the idea of a permanent label for your changesets, you can instead try the bookmarks extension. That will also give you "floating tags" which you can use for updating, but they wont be permanently part of the history since they aren't versioned.

I hope this helps a bit.

like image 194
Martin Geisler Avatar answered Oct 29 '22 03:10

Martin Geisler


The choice of method for tagging definitely has some odd side effects, but they're explained well in this wiki. It's also suggested that you clone an entire repo and then update to the point of interest to avoid the case where you will have created a repo that does not contain the tag that was used to create it.

like image 25
Dave Johansen Avatar answered Oct 29 '22 04:10

Dave Johansen