Counterintuitive tag behaviour (broken design?)

Chris Quenelle Chris.Quenelle at Sun.COM
Tue Mar 13 22:32:15 CDT 2007


I wrote the text after "----" first.  Then I remembered
to ask my simple question up front.  Why should we be searching
multiple different branches for tags?  Why aren't we just
using the "current CS" as the complete set of tags?
If your tree is assigned to a branch then use the branch tags.
Otherwise use the tip-tags only.  I read the recent emails on this
subject looking for a justification for why you need to search
all the branches, but I didn't see one.

A similar surprise came up with my use of "hg log" a few weeks ago.
(See below the "------")  It resulted in me deciding not to use
non-local tags until someone explained how to use them in a
non-confusing way.

My situation might be special because I'm using hg to maintain and resolve
two long-term branches.  So I have lots of special 'hg diff' aliases
and I often have to use 'update' to set myself back to specific versions
over and over again.  I might be using hg more "intensely" in this
respect than what is normally done. (Or maybe not)

So what follows is my story...

----------

I was surprised a few weeks ago by some strange tag behavior.

(What's the official term for "currently set/assigned CS" ?
In other words a name for "current output of 'hg id'"
I'll call it "current CS" for now)

I was adding some various tags to changesets and realized that
not all my tags were showing up in "hg log" output.
It turned out my current working CS (via update -C NN)
was set to a CS from before I added the tags.  So later tags
didn't show up in the "hg log" output.  But the CS's that
were the target of the tags *did* show up (obviously).
It doesn't make sense for a CS defined after my current CS
to show up in the output, but a tag defined after my current CS
to be hidden.

Of course, if I think about how it works, then it makes sense
that the .hgtags file being used is the version from the current CS.
But it could easily be implemented a different way.

Anyway, if you want to claim that "hg log" output is relative
to the current CS, that's okay, but then the log output should
only show CS's that contribute to the current state.
(Other CS's could be hidden with a warning or something)
Then you could have "hg log -a" show everything or something like that.

Otherwise, if "hg log" is supposed to show global output,
then make it independent of what the current CS is, and
use all the various .hgtags versions to attribute tags
to CS's.  In this case you bite off the problem of establishing a
"global tag context".  That's problem that's been discussed in
this thread recently.  But the problem is there is no true
"global context" because tags are applied or move *locally*
within a changeset.

--chris



Johan Herland wrote:
> Hi,
> I've been using Mercurial for a little while, and so far I really like it a 
> lot. However, in the last couple of days, I've started experimenting with 
> tags, and what I found was first puzzling, and after some more 
> experimentation my feeling can be best described as disbelief. Now, this may 
> be a big misunderstanding on my part as to how tags behave in Mercurial, but 
> I'd like to run this by you anyway.
> 
> Consider the following scenario (similar scenarios have been discussed before 
> on this mailing list according to the archives):
> 
> <command-line session>
> $ hg init
> $ touch a
> $ hg add a
> $ hg commit -m"Added a."
> $ echo "foo" > a
> $ hg commit -m"foo -> a."
> $ hg tag baz
> $ hg up 0
> 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
> $ echo "bar" > a
> $ hg commit -m"bar -> a."
> $ hg tag baz
> $ hg heads
> changeset:   4:9f14afcf590f
> tag:         tip
> summary:     Added tag baz for changeset e0c70b2c94aa
> 
> changeset:   2:eb6ad0bee830
> summary:     Added tag baz for changeset 27dbcef48adb
> $ hg tags
> tip                                4:9f14afcf590f
> baz                                3:e0c70b2c94aa
> $ hg up -C 2
> 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
> $ hg tags
> tip                                4:9f14afcf590f
> baz                                3:e0c70b2c94aa
> </command-line session>
> 
> So far, everything is ok. The latter tag command in rev.4 overrides the one in 
> rev.2 [1], and this is the case no matter which of the two branches I'm 
> currently on.
> 
> Now, consider I make some totally unrelated changes to the first branch:
> <command-line session>
> $ hg id
> eb6ad0bee830 (i.e. rev.2)
> $ echo "spam" >> a
> $ hg commit -m"spam -> a."
> $ hg heads
> changeset:   5:f0a5156412fb
> tag:         tip
> parent:      2:eb6ad0bee830
> summary:     spam -> a.
> 
> changeset:   4:9f14afcf590f
> summary:     Added tag baz for changeset e0c70b2c94aa
> $ hg tags
> tip                                5:f0a5156412fb
> baz                                1:27dbcef48adb
> $ hg up -C 4
> 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
> $ hg tags
> tip                                5:f0a5156412fb
> baz                                1:27dbcef48adb
> </command-line session>
> 
> As you can see, by performing an unrelated commit on the first branch, 
> the "baz" tag has changed on BOTH branches. I cannot in any way see WHY an 
> unrelated commit should change the meaning of a tag, much less change the 
> meaning of a tag on an entirely unrelated branch.
> 
> Now, after reading some discussions on the mailing list and in the bug 
> tracker, I think I understand _what_ Mercurial does in this situation [2], 
> but I cannot at all believe that what I'm seeing is (A) intuitive, and (B) 
> has been consciously designed/decided to be the intended result. To me, it 
> seems more like an unintended consequence/side-effect of the way tags 
> currently work in Mercurial.
> 
> After thinking about this issue for a while, I'm starting to question the way 
> tags are designed in Mercurial. Although I'm very sympathetic to the basic 
> idea of revision controlling tags, I have a hard time seeing that the idea is 
> successfully implemented in Mercurial. Even though the .hgtags file itself is 
> revision controlled, the lookup/resolving of tag names goes across all 
> branches/heads with preference to some arbitrary measure (tipmost-ness), and 
> thus seems to break the integrity of the revision control system (e.g. by 
> resulting in consequences as seen above).
> 
> If someone could please enlighten me as to what I don't get about the current 
> design, and why the current behaviour is desirable, I would be most 
> grateful. Otherwise, if the current behaviour is in fact not desirable, it 
> would be interesting to discuss how the behaviour can be revised in time for 
> the 1.0 release.
> 
> 
> Have fun!
> 
> ...Johan
> 
> 
> [1]: Well, not entirely ok... I'd very much like for "hg tag" to refuse to 
> move an existing tag without being given a "--force" argument (cf. CVS, git, 
> and most other rev.control systems, I guess).
> 
> [2]: Mercurial resolves tag names by looking them up on all repository heads, 
> with a preference towards the tipmost tag definitions. When resolving 
> the "baz" tag name, the tag definition made in rev.2 is suddenly closer to 
> the tip than the one in rev.4, because of the (unrelated) commit in rev.5.
> 


More information about the Mercurial mailing list