git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: git-tag bug? confusing git fast-export with double tag objects

From
Michael J Gruber <git@drmicha.warpmail.net>
Date
May 14, 2009, 12:00 UTC
Message-ID
<4A0C07D9.8030401@drmicha.warpmail.net>
In-Reply-To
<op.utwyczlf1e62zd@merlin.emma.line.org>
Matthias Andree venit, vidit, dixit 14.05.2009 11:37:
Show 120 quoted lines
> Am 14.05.2009, 05:18 Uhr, schrieb Junio C Hamano <gitster@pobox.com>:
> 
>> "Matthias Andree" <matthias.andree@gmx.de> writes:
>>
>>> Am 14.05.2009, 02:53 Uhr, schrieb Matthias Andree  
>>> <matthias.andree@gmx.de>:
>>>
>>>> 2. how do I trash the accidentally created 2nd "baz" tag object,
>>>> i. e.  remove it from the (packed) object database? Of course, I can
>>>> hack some  script (or use a text editor) to grind this
>>>> git-fast-export into shape  and re-importing it...
>>>
>>> OK, that worked: I traced (with git cat-file) the tree through all
>>> tagged  tag until the first tagged commit, and hack packed-refs (or
>>> refs/tags/foo)  to point to the commit object, and afterwards prune
>>> the dangling tag.
>>>
>>> However, the other questions remain. I'd think git tag should
>>> dereference  its 2nd non-option argument to a commit before laying
>>> down the tag...
>>
>> No.  You can tag any object, and a tag is an object.  You can point a
>> signed tag with your own signed tag to attest your own belief on that
>> other guy's tag, be it "it's genuine", "the tagged commit suits my need",
>> etc.
> 
> OK, so I can tag/sign any object, fine.
> 
> HOWEVER, I see two problems here (yes, they are corner cases):
> 
> #1: git tag -f ("replace tag") fails to "replace" a heaviweight tag if I  
> try to replace a tag by itself (or create a cycle by some other means).
> 
> The new "foo" is unique in refs (OK), but it's *not unique* in objects  
> (FAIL), as the old "foo" is referenced by the new "foo" and bears the same  
> tag name.
> 
> It screws the repo, breaking the uniqueness of tags. Basically, git tag -f  
> is implementing a half-baked, non-working "rebase tag objects"  
> functionality.
> 
> 
> 
> #2: related: git tag -d cannot reliably delete tag objects
> 
> Same here: if another tag object references the tag object I'm deleting,  
> we only delete the ref, but not the tag object. It doesn't (cannot) become  
> dangling.
> 
> 
> 
> Watch:
> 
> $ cd $(mktemp -d)
> $ git init
> Initialized empty Git repository in /tmp/tmp.GBjHED4Xj8/.git/
> $ date >a
> $ git add a
> $ git commit -m "new file a" -a
> [master (root-commit) 4481a15] new file a
>   1 files changed, 1 insertions(+), 0 deletions(-)
>   create mode 100644 a
> $ LANG=C git tag foo -m "add tag foo" -s
> [GPG passphrase query]
> $ LANG=C git tag foo foo -m "add tag foo" -s
> fatal: tag 'foo' already exists
> 
> -> this is ok, now let's break uniqueness:
> 
> $ LANG=C git tag foo foo -m "add tag foo" -s -f
> [GPG passphrase query]
> $ git rev-list --objects --all
> 4481a15d999b1b13066fe932e35ea05b8b1027a6
> 72f3463f5a8089ac91001d458ceffb6d4e1056ee foo
> 2e326d8a210536b7cd1f2bc77e3e29d7231f9ec4 foo
> 995773fc9b649922936e110207e6abb904cc18e8
> 15a9779d8f787428e57830410c7842e5449dfd33 a
> $ git show-ref
> 4481a15d999b1b13066fe932e35ea05b8b1027a6 refs/heads/master
> 72f3463f5a8089ac91001d458ceffb6d4e1056ee refs/tags/foo
> $ git cat-file tag 72f346
> object 2e326d8a210536b7cd1f2bc77e3e29d7231f9ec4
> type tag
> tag foo
> tagger Matthias Andree <matthias.andree@gmx.de> 1242289836 +0200
> 
> add tag foo
> -----BEGIN PGP SIGNATURE-----
> ...
> $
> $ git cat-file tag 2e326d
> object 4481a15d999b1b13066fe932e35ea05b8b1027a6
> type commit
> tag foo
> tagger Matthias Andree <matthias.andree@gmx.de> 1242289732 +0200
> 
> add tag foo
> -----BEGIN PGP SIGNATURE-----
> ...
> 
> 
> So what we get is (root/parents first, then children):
> 
> objects:  4481a1 (commit) <- 2e326d (tag "foo") <- 72f346 (tag "foo")
> refs:     heads/master                             tags/foo
> 
> Whoops. "foo" is there twice, and it's referenced from a current ref.
> We have *not* *replaced* it. *If* we did, we should have got:
> 
> objects:  4481a1 (commit) <- 72f346 (tag "foo")
> refs:     heads/master       tags/foo
> with a dangling tag 2e326d
> 
>> I thought there was a breakage report followed by a fix to the  
>> fast-export that mishandled a tag that points at another tag not too  
>> long ago.  Do you have 1982467 (builtin-fast-export.c: handle nested  
>> tags, 2009-03-23)?
> 
> I have that beast (how do I QUICKLY check if that is reachable from  
> refs/master? git log | grep isn't exactly quick), 

"git branch --contains 1982467" gives you all branches which have that. "git rev-list -1 "master..1982467|wc -l" checks whether 1982467 is contained in master.

but I think that's
Show 76 quoted lines
> unrelated. The real problem is the tag name is no longer unique, and we  
> must prevent that.
> 
> Let's screw with the tag objects even more (fresh repo, some "otherfile"):
> 
> $ git tag -m "old tag1" -a tag1
> $ git tag -m "tag2" -a tag2 tag1
> $ git tag -m "new tag1" tag1 tag2
> fatal: tag 'tag1' already exists
> $ git tag -f -m "new tag1" tag1 tag2
> $ git rev-list --objects tag1
> 69bf327c5d172fc8e4f63acf4d2e01c474824ce4
> 8e7a1997726fc5158954569134d2cafad710f6fe tag1
> 38aea56fec319d8c259a80157dde2432d2d09b2b tag2
> 9756f6fa98a5cce2aab1f6a6e7dd4de515626e19 tag1
> d758baa57a7ef20d44df0535bef1a91bb3dc4f62
> d3d8863b140f43f7c07050b9f2e210d41e73edb1 otherfile
> $ git show-ref
> 69bf327c5d172fc8e4f63acf4d2e01c474824ce4 refs/heads/master
> 8e7a1997726fc5158954569134d2cafad710f6fe refs/tags/tag1
> 38aea56fec319d8c259a80157dde2432d2d09b2b refs/tags/tag2
> $ gitk
> $ git cat-file tag 8e7a
> object 38aea56fec319d8c259a80157dde2432d2d09b2b
> type tag
> tag tag1
> tagger Matthias Andree <matthias.andree@gmx.de> 1242292320 +0200
> 
> new tag1
> $ git cat-file tag 38ae
> object 9756f6fa98a5cce2aab1f6a6e7dd4de515626e19
> type tag
> tag tag2
> tagger Matthias Andree <matthias.andree@gmx.de> 1242292301 +0200
> 
> tag2
> $ git cat-file tag 9756
> object 69bf327c5d172fc8e4f63acf4d2e01c474824ce4
> type commit
> tag tag1
> tagger Matthias Andree <matthias.andree@gmx.de> 1242292293 +0200
> 
> old tag1
> 
> Hu, there's a nice cycle:
> 
> 69bf (commit) <- 9756 ('old' tag1) <- 38ae (tag2) <- 8e7a (tag1)
> 
> Now, more fun - watch the inconsistency:
> 
> $ git tag -d tag1
> Deleted tag 'tag1'
> $ git tag -d tag1
> error: tag 'tag1' not found.
> 
> Ha! As if... now watch this:
> $ git rev-list --objects  --all | while read a b ; do echo "$a $(git  
> cat-file -t $a) $b" ; done
> 69bf327c5d172fc8e4f63acf4d2e01c474824ce4 commit
> 38aea56fec319d8c259a80157dde2432d2d09b2b tag tag2
> 9756f6fa98a5cce2aab1f6a6e7dd4de515626e19 tag tag1
> d758baa57a7ef20d44df0535bef1a91bb3dc4f62 tree
> d3d8863b140f43f7c07050b9f2e210d41e73edb1 blob otherfile
> 
> The tag object "tag1" is still there. WHOOPS!!!
> 
> I appreciate that this isn't trivial to solve, but I presume anything that  
> walks the object database and uses tags can fail - including, but not  
> limited to, git fast-export.
> 
> Either git tag -f/-d should complain and refuse if it cannot  
> replace/remove the tag because it wouldn't become dangling (other  
> dependencies on it, best to list them), or it would have to recursively  
> trash all its children, too - and perhaps require -f -f be specified for  
> this recursive replacing/removal.
> 
Previous: Matthias AndreeNext: Alex Riesen
Message 5 of 30 in “git-tag bug? confusing git fast-export with double tag objects”
  1. Matthias AndreeMay 14, 2009
  2. Matthias AndreeMay 14, 2009
  3. Junio C HamanoMay 14, 2009
  4. Matthias AndreeMay 14, 2009
  5. Michael J GruberMay 14, 2009
  6. Alex RiesenMay 14, 2009
  7. Matthias AndreeMay 14, 2009
  8. Alex RiesenMay 14, 2009
  9. Matthias AndreeMay 14, 2009
  10. Sverre RabbelierMay 14, 2009
  11. Matthias AndreeMay 14, 2009
  12. Brandon CaseyMay 14, 2009
  13. Jeff KingMay 14, 2009
  14. Matthias AndreeMay 14, 2009
  15. Jeff KingMay 15, 2009
  16. Matthias AndreeMay 15, 2009
  17. Jakub NarebskiMay 15, 2009
  18. Johannes SixtMay 15, 2009
  19. Alex RiesenMay 15, 2009
  20. Matthias AndreeMay 15, 2009
  21. Andreas EricssonMay 15, 2009
  22. Junio C HamanoMay 15, 2009
  23. Andreas EricssonMay 16, 2009
  24. Jakub NarebskiMay 16, 2009
  25. Andreas EricssonMay 16, 2009
  26. Junio C HamanoMay 16, 2009
  27. Matthias AndreeMay 19, 2009
  28. Jeff KingMay 19, 2009
  29. Jeff KingMay 16, 2009
  30. Daniel ChengMay 15, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.