mpen
mpen

Reputation: 282915

How do tags *actually* work?

The docs say all the tags are stored in .hgtags, but there's clearly some black magic going on here.

My tags look like this:

mbayazit:~/test$ cat .hgtags 
0d80b6ba4ba3b51a44f0f1d339fcac1d4b21f387 stable
c70d8e7e516d8b9e0c520063a575b4acea1b2f94 testtag
0d80b6ba4ba3b51a44f0f1d339fcac1d4b21f387 stable
b1a360af6daf536ddc55b6b50127e88c30a227dc stable

If I update to testtag,

mbayazit:~/test$ hg up testtag
1 files updated, 0 files merged, 2 files removed, 0 files unresolved

The tags disappear,

mbayazit:~/test$ cat .hgtags 
cat: .hgtags: No such file or directory

Because testtag is older than the others; why it's out of order I don't know.

But when I try to update to stable again,

mbayazit:~/test$ hg up stable
3 files updated, 0 files merged, 0 files removed, 0 files unresolved

It magically works. How is that possible if that tag isn't even in .hgtags?

Upvotes: 3

Views: 255

Answers (2)

Ry4an Brase
Ry4an Brase

Reputation: 78340

The available tags are the union of all the .hgtags in all the heads of your repo. So to see everything you'd need to see what .hgtags looks like in every revision that shows up in hg heads. @black_wizard has a great explanation of why you don't see your tag in .hgtags when you update to them, and "the .hgtags file is read from the hg heads" is why they still work.

Upvotes: 4

rpeshkov
rpeshkov

Reputation: 5047

In the second section of the official tags documentation written this statement:

Updating a working dir to a particular tag will take that directory back to a point before the tag itself existed.

For the first time .hgtags file is created when you tag particular revision. When you update your repository state to this tagged revision, state of your repository is actually right before the .hgtags been added to version control.

Here's the example when we add first tag and then update repository state to this tagged revision:

PS D:\tagstest> hg init
PS D:\tagstest [default tip]> echo 'Something' > readme.txt
PS D:\tagstest [default ?1 tip]> hg addremove
adding readme.txt
PS D:\tagstest [default +1 tip]> hg ci -m "First commit"
PS D:\tagstest [default tip]> hg tag first
PS D:\tagstest [default tip]> cat .\.hgtags
9494cb0dc308d91ecae8514a341c2fa2324d3ade first
PS D:\tagstest [default tip]> hg update first
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
PS D:\tagstest [default first]> cat .\.hgtags
cat : Cannot find path 'D:\tagstest\.hgtags' because it does not exist.

This case is just what you described in your question. But let's go further and add another tag:

PS D:\tagstest [default first]> hg up tip
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
PS D:\tagstest [default tip]> echo 'Something else' >> .\readme.txt
PS D:\tagstest [default ~1 tip]> hg ci -m "second commit"
PS D:\tagstest [default tip]> hg tag second
PS D:\tagstest [default tip]> cat .\.hgtags
9494cb0dc308d91ecae8514a341c2fa2324d3ade first
8b0455fffb17c978ef9e285905d76e34feae32f4 second
PS D:\tagstest [default tip]> hg up second
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
PS D:\tagstest [default second]> cat .\.hgtags
9494cb0dc308d91ecae8514a341c2fa2324d3ade first

Here you can see that after updating repository state to second tag .hgtags file didn't dissapear, but there's just first tag because the state of repository is just before second tag was added to .hgtags file.

Update:

In your case it looks like that you've added first tag stable (that caused creation of .hgtags file) to revision 0d80b6ba4ba3b51a44f0f1d339fcac1d4b21f387 after revision c70d8e7e516d8b9e0c520063a575b4acea1b2f94 was created (that you tagged with testtag). So when you update repository state to testtag revision, there's no .hgtags file because it hasn't been created yet.

Example:

PS D:\tagstest2> hg init
PS D:\tagstest2 [default tip]> echo "Something" > readme.txt
PS D:\tagstest2 [default ?1 tip]> hg addremove
adding readme.txt
PS D:\tagstest2 [default +1 tip]> hg ci -m "First commit"
PS D:\tagstest2 [default tip]> echo "Something else" > .\readme.txt
PS D:\tagstest2 [default ~1 tip]> hg ci -m "Second commit"
PS D:\tagstest2 [default tip]> echo "Something more" >> .\readme.txt
PS D:\tagstest2 [default ~1 tip]> hg ci -m "Third commit"
PS D:\tagstest2 [default tip]> hg tag -r 0 first
PS D:\tagstest2 [default tip]> hg tag -r 1 second
PS D:\tagstest2 [default tip]> hg gl
@  4[tip]   a0753742f012   2013-08-21 00:29 +0400   peshkovroman
|    Added tag second for changeset 7e4896c8ef3e
|
o  3   cee5760a9d1c   2013-08-21 00:29 +0400   peshkovroman
|    Added tag first for changeset 12f055c90ee8
|
o  2   f4c00a7394e1   2013-08-21 00:29 +0400   peshkovroman
|    Third commit
|
o  1[second]   7e4896c8ef3e   2013-08-21 00:28 +0400   peshkovroman
|    Second commit
|
o  0[first]   12f055c90ee8   2013-08-21 00:28 +0400   peshkovroman

When you call hg up second, your repository state will be updated to revision 1, but .hgtags was created only in revision 2.

Upvotes: 5

Related Questions