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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Matthias Andree venit, vidit, dixit 14.05.2009 11:37:
> Am 14.05.2009, 05:18 Uhr, schrieb Junio C Hamano <gitster@xxxxxxxxx>:
> 
>> "Matthias Andree" <matthias.andree@xxxxxx> writes:
>>
>>> Am 14.05.2009, 02:53 Uhr, schrieb Matthias Andree  
>>> <matthias.andree@xxxxxx>:
>>>
>>>> 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@xxxxxx> 1242289836 +0200
> 
> add tag foo
> -----BEGIN PGP SIGNATURE-----
> ...
> $
> $ git cat-file tag 2e326d
> object 4481a15d999b1b13066fe932e35ea05b8b1027a6
> type commit
> tag foo
> tagger Matthias Andree <matthias.andree@xxxxxx> 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@xxxxxx> 1242292320 +0200
> 
> new tag1
> $ git cat-file tag 38ae
> object 9756f6fa98a5cce2aab1f6a6e7dd4de515626e19
> type tag
> tag tag2
> tagger Matthias Andree <matthias.andree@xxxxxx> 1242292301 +0200
> 
> tag2
> $ git cat-file tag 9756
> object 69bf327c5d172fc8e4f63acf4d2e01c474824ce4
> type commit
> tag tag1
> tagger Matthias Andree <matthias.andree@xxxxxx> 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.
> 

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]