From: Michael J Gruber <git@drmicha.warpmail.net>
To: Matthias Andree <matthias.andree@gmx.de>
Cc: Junio C Hamano <gitster@pobox.com>,
git@vger.kernel.org, Erik Faye-Lund <kusmabite@gmail.com>
Subject: Re: git-tag bug? confusing git fast-export with double tag objects
Date: Thu, 14 May 2009 14:00:25 +0200 [thread overview]
Message-ID: <4A0C07D9.8030401@drmicha.warpmail.net> (raw)
In-Reply-To: <op.utwyczlf1e62zd@merlin.emma.line.org>
Matthias Andree venit, vidit, dixit 14.05.2009 11:37:
> 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
> 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.
>
next prev parent reply other threads:[~2009-05-14 12:00 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-05-14 0:53 git-tag bug? confusing git fast-export with double tag objects Matthias Andree
2009-05-14 2:13 ` Matthias Andree
2009-05-14 3:18 ` Junio C Hamano
2009-05-14 9:37 ` Matthias Andree
2009-05-14 12:00 ` Michael J Gruber [this message]
2009-05-14 12:16 ` Alex Riesen
2009-05-14 12:51 ` Matthias Andree
2009-05-14 13:16 ` Alex Riesen
2009-05-14 13:39 ` Matthias Andree
2009-05-14 13:42 ` Sverre Rabbelier
2009-05-14 18:02 ` Matthias Andree
2009-05-14 19:01 ` Brandon Casey
2009-05-14 18:22 ` Jeff King
2009-05-14 22:35 ` Matthias Andree
2009-05-15 2:02 ` Jeff King
2009-05-15 12:23 ` Matthias Andree
2009-05-15 13:22 ` Jakub Narebski
2009-05-15 14:54 ` Johannes Sixt
2009-05-15 15:51 ` Alex Riesen
2009-05-15 16:14 ` Matthias Andree
2009-05-15 16:21 ` Andreas Ericsson
2009-05-15 17:40 ` Junio C Hamano
2009-05-16 7:14 ` Andreas Ericsson
2009-05-16 7:56 ` Jakub Narebski
2009-05-16 8:02 ` Andreas Ericsson
2009-05-16 17:16 ` Junio C Hamano
2009-05-19 11:21 ` Matthias Andree
2009-05-19 11:29 ` Jeff King
2009-05-16 5:07 ` Jeff King
2009-05-15 16:00 ` Daniel Cheng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4A0C07D9.8030401@drmicha.warpmail.net \
--to=git@drmicha.warpmail.net \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=kusmabite@gmail.com \
--cc=matthias.andree@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).