git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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.
> 

  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).