* git-tag bug? confusing git fast-export with double tag objects
@ 2009-05-14 0:53 Matthias Andree
2009-05-14 2:13 ` Matthias Andree
0 siblings, 1 reply; 30+ messages in thread
From: Matthias Andree @ 2009-05-14 0:53 UTC (permalink / raw)
To: git
Greetings,
I found a way to break git fast-export accidentally. I'm looking at the
master branch, currently v1.6.3.1-9-g95405ba for me.
The short story is, I tried to regenerate signed tag objects after
doctoring the history in a repo to fix b0rked addresses after conversion,
doing something like:
git tag -f -s foo foo
when I should have done
git tag -f -s foo foo^{commit}
Now I have tag "foo" twice in my repo, and this screws some operations
royally.
Here's a script to generate such a b0rked repo:
#! /bin/sh
#
# On your marks
set -eu
IFS=$(printf '\n\t')
#
# Set
dir=$(mktemp -d)
cd $dir
git init
echo foo >bar
git add bar
git commit -m "add bar"
git tag -s baz -m "tag bar as baz"
#
# Go - this is correct, but we'll do wrong
#git tag -f -s baz baz^{commit} -m "regenerate tag"
#
# This is wrong and confuses git fast-export:
git tag -f -s baz baz -m "regenerate tag"
#
# Print the result
git show baz
This is quite prominent in git fast-export --all --signed-tags=strip
output:
...
tag baz
from :2
tagger Matthias Andree <matthias.andree@gmx.de> 1242259705 +0200
data 15
tag bar as baz
tag baz
from :0
tagger Matthias Andree <matthias.andree@gmx.de> 1242259705 +0200
data 11
regenerate
And the "from :0" hunk kills git fast-import afterwards as the mark :0
isn't defined. Not sure if it could cope with a duplicate tag otherwise.
Probably not how git-tag should behave.
Questions:
1. how do I get a list of all such tags? git tag -l doesn't work. git
rev-list --all is a bit unspecific for my taste, and not very helpful...
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...
3. is this a shortcoming in git tag that doesn't properly resolve its 2nd
non-option argument to a commit?
Thanks.
--
Matthias Andree
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
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
0 siblings, 1 reply; 30+ messages in thread
From: Matthias Andree @ 2009-05-14 2:13 UTC (permalink / raw)
To: git
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...
--
Matthias Andree
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 2:13 ` Matthias Andree
@ 2009-05-14 3:18 ` Junio C Hamano
2009-05-14 9:37 ` Matthias Andree
0 siblings, 1 reply; 30+ messages in thread
From: Junio C Hamano @ 2009-05-14 3:18 UTC (permalink / raw)
To: Matthias Andree; +Cc: git, Erik Faye-Lund
"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.
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)?
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 3:18 ` Junio C Hamano
@ 2009-05-14 9:37 ` Matthias Andree
2009-05-14 12:00 ` Michael J Gruber
` (3 more replies)
0 siblings, 4 replies; 30+ messages in thread
From: Matthias Andree @ 2009-05-14 9:37 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Erik Faye-Lund
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), 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.
--
Matthias Andree
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 9:37 ` Matthias Andree
@ 2009-05-14 12:00 ` Michael J Gruber
2009-05-14 12:16 ` Alex Riesen
` (2 subsequent siblings)
3 siblings, 0 replies; 30+ messages in thread
From: Michael J Gruber @ 2009-05-14 12:00 UTC (permalink / raw)
To: Matthias Andree; +Cc: Junio C Hamano, git, Erik Faye-Lund
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.
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 9:37 ` Matthias Andree
2009-05-14 12:00 ` Michael J Gruber
@ 2009-05-14 12:16 ` Alex Riesen
2009-05-14 12:51 ` Matthias Andree
2009-05-14 18:22 ` Jeff King
2009-05-15 16:00 ` Daniel Cheng
3 siblings, 1 reply; 30+ messages in thread
From: Alex Riesen @ 2009-05-14 12:16 UTC (permalink / raw)
To: Matthias Andree; +Cc: Junio C Hamano, git, Erik Faye-Lund
2009/5/14 Matthias Andree <matthias.andree@gmx.de>:
> Am 14.05.2009, 05:18 Uhr, schrieb Junio C Hamano <gitster@pobox.com>:
>> 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).
It is not a "cycle" ("loop"?) The tags information is the SHA1, not
the tag's name.
> 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.
Of course it is unique. Look at tag's SHA1.
> #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.
As soon as an object is not referenced anymore by any reference (including
references from refs/tags/), reference log or index it will be removed by
garbage collection (gc, prune) at the next opportunity.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 12:16 ` Alex Riesen
@ 2009-05-14 12:51 ` Matthias Andree
2009-05-14 13:16 ` Alex Riesen
0 siblings, 1 reply; 30+ messages in thread
From: Matthias Andree @ 2009-05-14 12:51 UTC (permalink / raw)
To: Alex Riesen; +Cc: Junio C Hamano, git, Erik Faye-Lund
Am 14.05.2009, 14:16 Uhr, schrieb Alex Riesen <raa.lkml@gmail.com>:
> 2009/5/14 Matthias Andree <matthias.andree@gmx.de>:
>> Am 14.05.2009, 05:18 Uhr, schrieb Junio C Hamano <gitster@pobox.com>:
>>> 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).
>
> It is not a "cycle" ("loop"?) The tags information is the SHA1, not
> the tag's name.
>
>> 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.
>
> Of course it is unique. Look at tag's SHA1.
Hi Alex,
I'm sorry to say this is irrelevant. Please read my earlier message again,
and completely this time - you appear to have missed crucial parts, as
your next paragraph suggests:
>> #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.
>
> As soon as an object is not referenced anymore by any reference
> (including references from refs/tags/), reference log or index it will
> be removed by
> garbage collection (gc, prune) at the next opportunity.
Irrelevant, because your assumption "not referenced anymore" is false.
This was clearly written in my earlier message, which please see.
--
Matthias Andree
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 12:51 ` Matthias Andree
@ 2009-05-14 13:16 ` Alex Riesen
2009-05-14 13:39 ` Matthias Andree
0 siblings, 1 reply; 30+ messages in thread
From: Alex Riesen @ 2009-05-14 13:16 UTC (permalink / raw)
To: Matthias Andree; +Cc: Junio C Hamano, git, Erik Faye-Lund
2009/5/14 Matthias Andree <matthias.andree@gmx.de>:
> Am 14.05.2009, 14:16 Uhr, schrieb Alex Riesen <raa.lkml@gmail.com>:
>>
>> As soon as an object is not referenced anymore by any reference (including
>> references from refs/tags/), reference log or index it will be removed by
>> garbage collection (gc, prune) at the next opportunity.
>
> Irrelevant, because your assumption "not referenced anymore" is false. This
> was clearly written in my earlier message, which please see.
Yes, in your case it stays referenced, through the new tag which the reference
refs/tags/foo _now_ points to. Tough luck. In this particular case you could
just remove the reference (that's refs/tags/foo now), repack and re-tag
(properly).
It may be not what your wanted, but it is how it is expected to work. If git tag
would reduce its arguments down to commits, it would be impossible to sign
tags at all (strictly speaking: it would be impossible to create a
tag, referencing
another tag). Which is useful thing to have.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 13:16 ` Alex Riesen
@ 2009-05-14 13:39 ` Matthias Andree
2009-05-14 13:42 ` Sverre Rabbelier
0 siblings, 1 reply; 30+ messages in thread
From: Matthias Andree @ 2009-05-14 13:39 UTC (permalink / raw)
To: Alex Riesen; +Cc: Junio C Hamano, git, Erik Faye-Lund
Am 14.05.2009, 15:16 Uhr, schrieb Alex Riesen <raa.lkml@gmail.com>:
> It may be not what your wanted, but it is how it is expected to work. If
> git tag would reduce its arguments down to commits, it would be
> impossible to sign tags at all (strictly speaking: it would be
> impossible to create a
> tag, referencing another tag). Which is useful thing to have.
I'll kindly ask you again: please read my messages completely and
carefully.
I gave up the idea of reducing tag objects to referencing commits two
messages ago. That was one simple, early, and insufficient suggestion of
mine to address the bug. It is no longer brought forward.
The bug itself (references to 'deleted' or 'replaced' tag objects remain
reachable rather than becoming dangling) is still there without a
suggestion to the solution, and you're uselessly the bug.
I may be wrong, but I do believe you still haven't understood my report -
this may well be a problem in my way of phrasing it. So let's try this:
If you do not understand parts of the problem, please ask specific
questions.
If you do not understand enough of this problem to ask such questions,
please ignore this thread.
Please do not waste someone else's time by keeping up a discussion of
arguments I've withdrawn hours ago.
I'm not going to repeat earlier reasons either.
--
Matthias Andree
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 13:39 ` Matthias Andree
@ 2009-05-14 13:42 ` Sverre Rabbelier
2009-05-14 18:02 ` Matthias Andree
0 siblings, 1 reply; 30+ messages in thread
From: Sverre Rabbelier @ 2009-05-14 13:42 UTC (permalink / raw)
To: Matthias Andree, Alex Riesen; +Cc: Junio C Hamano, git, Erik Faye-Lund
Heya,
On Thu, May 14, 2009 at 15:39, Matthias Andree <matthias.andree@gmx.de> wrote:
> The bug itself (references to 'deleted' or 'replaced' tag objects remain
> reachable rather than becoming dangling) is still there without a suggestion
> to the solution, and you're uselessly the bug.
I believe Alex is saying that this is not a bug, but intended
behavior, and Matthias is saying that we should change that behavior
so that users are at least aware that they are creating such a
situation, is that correct?
--
Cheers,
Sverre Rabbelier
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 13:42 ` Sverre Rabbelier
@ 2009-05-14 18:02 ` Matthias Andree
2009-05-14 19:01 ` Brandon Casey
0 siblings, 1 reply; 30+ messages in thread
From: Matthias Andree @ 2009-05-14 18:02 UTC (permalink / raw)
To: Sverre Rabbelier, Alex Riesen; +Cc: Junio C Hamano, git, Erik Faye-Lund
Am 14.05.2009, 15:42 Uhr, schrieb Sverre Rabbelier <srabbelier@gmail.com>:
> Heya,
>
> On Thu, May 14, 2009 at 15:39, Matthias Andree <matthias.andree@gmx.de>
> wrote:
>> The bug itself (references to 'deleted' or 'replaced' tag objects remain
>> reachable rather than becoming dangling) is still there without a
>> suggestion
>> to the solution, and you're uselessly the bug.
>
> I believe Alex is saying that this is not a bug, but intended
> behavior, and Matthias is saying that we should change that behavior
> so that users are at least aware that they are creating such a
> situation, is that correct?
I think my statements are:
1- git tag -d and git tag -f do not work as advertised for tag objects (as
opposed to lightweight tags); evidence in the longish mail
2- I presume that the bug cannot be really fixed (signed tags created by
somebody else), we then have several solutions:
2a- warn the user and refuse
2b- warn the user and continue nonetheless
2c- warn the user and add options to force the user should at least be
warned that he may be doing something which doesn't work as intended, or
2d- give the user a possibility to force git to do stupid things.
--
Matthias Andree
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 9:37 ` Matthias Andree
2009-05-14 12:00 ` Michael J Gruber
2009-05-14 12:16 ` Alex Riesen
@ 2009-05-14 18:22 ` Jeff King
2009-05-14 22:35 ` Matthias Andree
2009-05-15 16:00 ` Daniel Cheng
3 siblings, 1 reply; 30+ messages in thread
From: Jeff King @ 2009-05-14 18:22 UTC (permalink / raw)
To: Matthias Andree; +Cc: Junio C Hamano, git, Erik Faye-Lund
On Thu, May 14, 2009 at 11:37:37AM +0200, Matthias Andree wrote:
> 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.
Can you explain how this "screws the repo"? The refs are unique, and in
your examples, a tag object replaced by "git tag -f" no longer has a ref
pointing to it (but in your example of making a tag of a tag, then of
course the original is still reachable indirectly). The "unique in
objects" you refer to is that the tag itself says "here is the name
under which I was tagged". That name is purely informative and has
nothing to do with ref lookup or reachability.
In your examples, I don't see any behavior that is causing actual
problems.
> #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.
Deleting the ref makes it dangling, unless something else is referencing
it. In your examples, since you tag the tag, the original tag is still
referenced.
> $ git rev-list --objects --all
> 4481a15d999b1b13066fe932e35ea05b8b1027a6
> 72f3463f5a8089ac91001d458ceffb6d4e1056ee foo
> 2e326d8a210536b7cd1f2bc77e3e29d7231f9ec4 foo
> 995773fc9b649922936e110207e6abb904cc18e8
> 15a9779d8f787428e57830410c7842e5449dfd33 a
The right-hand side of this output is a purely informative "here is a
name that may be useful for packing heuristics". It has nothing to do
with the refs (for blobs, the pathname through which we reached the blob
will be printed -- obviously this is not going to be unique, as you will
have many versions of each file).
> 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
Right. Because you didn't ask to replace it. You asked to tag the tag.
> Hu, there's a nice cycle:
>
> 69bf (commit) <- 9756 ('old' tag1) <- 38ae (tag2) <- 8e7a (tag1)
You keep calling these cycles, but they're not (at least in terms of the
git graph). The fact that two distinct objects both contain the string
"tag tag1" is not any more a cycle than two commit objects with the same
commit message. They are both distinct objects with distinct hashes, and
the hashes are how the git graph is built.
> Now, more fun - watch the inconsistency:
>
> $ git tag -d tag1
> Deleted tag 'tag1'
> $ git tag -d tag1
> error: tag 'tag1' not found.
OK, so you deleted the ref tag1.
> 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!!!
Of course the _old_ tag1 is still there. It is referenced by tag2, which
still has a ref. Again you are confusing the right-hand side of "git
rev-list --objects" with actual ref names.
> 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.
I am not ruling out the possibility that there is some piece of code
that will be confused by the situation you have created, but it has
nothing to do with graph walking. It would have to be a piece of code
which cares about the uniqueness of informative names inside tag
objects.
-Peff
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 18:02 ` Matthias Andree
@ 2009-05-14 19:01 ` Brandon Casey
0 siblings, 0 replies; 30+ messages in thread
From: Brandon Casey @ 2009-05-14 19:01 UTC (permalink / raw)
To: Matthias Andree
Cc: Sverre Rabbelier, Alex Riesen, Junio C Hamano, git,
Erik Faye-Lund
Matthias Andree wrote:
> Am 14.05.2009, 15:42 Uhr, schrieb Sverre Rabbelier <srabbelier@gmail.com>:
>
>> Heya,
>>
>> On Thu, May 14, 2009 at 15:39, Matthias Andree
>> <matthias.andree@gmx.de> wrote:
>>> The bug itself (references to 'deleted' or 'replaced' tag objects remain
>>> reachable rather than becoming dangling) is still there without a
>>> suggestion
>>> to the solution, and you're uselessly the bug.
>>
>> I believe Alex is saying that this is not a bug, but intended
>> behavior, and Matthias is saying that we should change that behavior
>> so that users are at least aware that they are creating such a
>> situation, is that correct?
>
> I think my statements are:
>
> 1- git tag -d and git tag -f do not work as advertised for tag objects (as
> opposed to lightweight tags); evidence in the longish mail
Both of these do indeed work.
In your examples 'git tag -d' worked as intended. The tag was deleted even
though the object still remained in the object database. The tag subcommand
does not remove objects. Objects which are not used anymore are removed by
running the 'git gc' command. This happens automatically periodically. If
you want to see them disappear now, run 'git gc --prune=now'.
In your examples, 'git tag -f' worked as intended. The "object" referenced
by the command line arguments was tagged, and the existing tag was replaced
by a new tag with the same name.
So when you do
$ git tag -f -m 'add tag foo' foo foo
the second foo is dereferenced, and it's object id is what is tagged. So it
is equivalent to the following:
$ git tag -f -m 'add tag foo' foo 2e326d8a210536b7cd1f2bc77e3e29d7231f9ec4
This object happens to be a tag object which points to a commit.
Your graph:
objects: 4481a1 (commit) <- 2e326d (tag "foo") <- 72f346 (tag "foo")
is perfectly correct and valid. The middle tag object does not exist in
the tag namespace though. Its name is embedded in the tag object and is
necessary for validating the tag object.
> 2- I presume that the bug cannot be really fixed (signed tags created by
> somebody else), we then have several solutions:
> 2a- warn the user and refuse
> 2b- warn the user and continue nonetheless
> 2c- warn the user and add options to force the user should at least be
> warned that he may be doing something which doesn't work as intended, or
> 2d- give the user a possibility to force git to do stupid things.
There are no 'cycles', there is no inconsistency, there is no bug, except
perhaps in git fast-export.
-brandon
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 18:22 ` Jeff King
@ 2009-05-14 22:35 ` Matthias Andree
2009-05-15 2:02 ` Jeff King
0 siblings, 1 reply; 30+ messages in thread
From: Matthias Andree @ 2009-05-14 22:35 UTC (permalink / raw)
To: Jeff King
Cc: Junio C Hamano, git, Alex Riesen, Brandon Casey, Sverre Rabbelier
Am 14.05.2009, 20:22 Uhr, schrieb Jeff King <peff@peff.net>:
> On Thu, May 14, 2009 at 11:37:37AM +0200, Matthias Andree wrote:
>
>> 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.
>
> Can you explain how this "screws the repo"? The refs are unique, and in
> your examples, a tag object replaced by "git tag -f" no longer has a ref
> pointing to it (but in your example of making a tag of a tag, then of
> course the original is still reachable indirectly). The "unique in
> objects" you refer to is that the tag itself says "here is the name
> under which I was tagged". That name is purely informative and has
> nothing to do with ref lookup or reachability.
>
> In your examples, I don't see any behavior that is causing actual
> problems.
Hi Jeff,
so you, Alex and Brandon say git doesn't malfunction here. Hope you don't
mind my insisting, and to keep this concise, I'll send only one answer to
several posts (the whole discussion is too verbose already).
I agree that the resulting object structure is still a directed acyclic
graph, so I'll not criticize the object structure.
The semantic meaning however is missing. Let me take a different vantage
and look at the same situation, leaving the object graph aside.
This "git tag -f -s same same" operation gives me a signed nothing, and
the ref indeed no longer points to the old tag. But what's the new
signature or tag good for? I tagged & signed an object that was removed
in the process. I have a tagged and signed nothing. (Yes, there is an
underlying object, but it takes lots of fiddling with the LL tools to get
at it.)
> Deleting the ref makes it dangling, unless something else is referencing
> it. In your examples, since you tag the tag, the original tag is still
> referenced.
That's what I see, yes. But again, what good is the signed nothing?
> Of course the _old_ tag1 is still there. It is referenced by tag2, which
> still has a ref. Again you are confusing the right-hand side of "git
> rev-list --objects" with actual ref names.
Indeed it's not git show-ref...
> I am not ruling out the possibility that there is some piece of code
> that will be confused by the situation you have created, but it has
> nothing to do with graph walking. It would have to be a piece of code
> which cares about the uniqueness of informative names inside tag
> objects.
That's true, and apparently git fast-export is one of those pieces of code.
Thanks
--
Matthias Andree
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 22:35 ` Matthias Andree
@ 2009-05-15 2:02 ` Jeff King
2009-05-15 12:23 ` Matthias Andree
0 siblings, 1 reply; 30+ messages in thread
From: Jeff King @ 2009-05-15 2:02 UTC (permalink / raw)
To: Matthias Andree
Cc: Junio C Hamano, git, Alex Riesen, Brandon Casey, Sverre Rabbelier
On Fri, May 15, 2009 at 12:35:45AM +0200, Matthias Andree wrote:
> The semantic meaning however is missing. Let me take a different vantage
> and look at the same situation, leaving the object graph aside.
>
> This "git tag -f -s same same" operation gives me a signed nothing, and
> the ref indeed no longer points to the old tag.
It doesn't give you a signed nothing. It gives you a signed tag pointing
to the old signed tag (which in turn could point to another tag, a
commit, etc).
And yes, the ref no longer points to the old tag. That has nothing to do
with what you are pointing the tag out, but the fact that you are
_overwriting_ the old tag. And we already have a safety valve there: you
must specify "-f" to overwrite an existing tag.
> But what's the new signature or tag good for?
Tagging a tag is good for saying something about the original tag, as
opposed to saying something about the commit that the original tag
points to.
> I tagged & signed an object that was removed in the process. I have
> a tagged and signed nothing. (Yes, there is an underlying object, but
> it takes lots of fiddling with the LL tools to get at it.)
The object wasn't removed, any more than making a new commit that
advances a branch head removes the old history. Git objects form a DAG,
and refs are named objects in the DAG. But we only consider objects
"removed" when they are not reachable from any ref (and I say "removed"
because we call this "dangling", and then actually remove them after
they have been dangling for a period of time, assuming that nobody is
interested in them any longer). And it is not the case here that the
result is dangling.
I wouldn't be surprised if working with tags of tags is less convenient,
because people aren't using them as often as tags of commits, and there
may be some unexercised corner cases. But you can certainly see them via
"git show":
$ git init && echo content > file && git add . && git commit -m one
$ git tag -m two tag1
$ git tag -m three tag2 tag1
$ git show tag2
should show something like:
tag tag2
Tagger: Jeff King <peff@peff.net>
Date: Thu May 14 21:06:09 2009 -0400
three
tag tag1
Tagger: Jeff King <peff@peff.net>
Date: Thu May 14 21:05:44 2009 -0400
two
commit 395553770322cbfc8326eb6edc9c3ab73334c541
Author: Jeff King <peff@peff.net>
Date: Thu May 14 21:05:27 2009 -0400
one
diff...
Arguably the spacing could be more readable (one less blank line between
the tag header and its message, and an extra space between the message
and the start of the next header), but I wouldn't call the tag
inaccessible or removed.
And you can repeat the same exercise with
$ git tag -f -m four tag2 tag2
which will show you the chain of tag2 -> old_tag2 -> tag1 -> commit.
>> Of course the _old_ tag1 is still there. It is referenced by tag2, which
>> still has a ref. Again you are confusing the right-hand side of "git
>> rev-list --objects" with actual ref names.
>
> Indeed it's not git show-ref...
Right. No ref points to it any more. But that doesn't mean it's not
there. Just like older commits have no ref pointing to them, and we have
to give them names based on the refs we do have, like HEAD~5. There is
not a shorthand syntax for saying "peel exactly N layers of this tag
chain", but I think that is because nobody has really needed one at this
point.
>> I am not ruling out the possibility that there is some piece of code
>> that will be confused by the situation you have created, but it has
>> nothing to do with graph walking. It would have to be a piece of code
>> which cares about the uniqueness of informative names inside tag
>> objects.
>
> That's true, and apparently git fast-export is one of those pieces of code.
Sorry, I thought from your last email ("I presume anything that walks
the object database and uses tags can fail") that you were just
speculating on fast-export mishandling.
Going back to your original message, though, it looks like you do have a
specific problem with fast-export. However, I think it has nothing to do
with a _renamed_ tag, but in general of tags pointing to tags. The
outermost tag ends up pointing to a bogus mark of ":0".
I would have thought that would be dealt with by 198246, but I can
replicate the problem even on the current 'next'. I think we just need
to be setting a mark for tag objects. The patch below makes your
fast-export example better, but it still looks like we end up printing
out one of the tag objects twice.
---
diff --git a/builtin-fast-export.c b/builtin-fast-export.c
index 6731713..2349c8d 100644
--- a/builtin-fast-export.c
+++ b/builtin-fast-export.c
@@ -293,6 +293,9 @@ static void handle_tag(const char *name, struct tag *tag)
buf = read_sha1_file(tag->object.sha1, &type, &size);
if (!buf)
die ("Could not read tag %s", sha1_to_hex(tag->object.sha1));
+
+ mark_next_object(&tag->object);
+
message = memmem(buf, size, "\n\n", 2);
if (message) {
message += 2;
@@ -335,8 +338,8 @@ static void handle_tag(const char *name, struct tag *tag)
if (!prefixcmp(name, "refs/tags/"))
name += 10;
- printf("tag %s\nfrom :%d\n%.*s%sdata %d\n%.*s\n",
- name, get_object_mark(tag->tagged),
+ printf("tag %s\nmark :%"PRIu32"\nfrom :%d\n%.*s%sdata %d\n%.*s\n",
+ name, last_idnum, get_object_mark(tag->tagged),
(int)(tagger_end - tagger), tagger,
tagger == tagger_end ? "" : "\n",
(int)message_size, (int)message_size, message ? message : "");
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-15 2:02 ` Jeff King
@ 2009-05-15 12:23 ` Matthias Andree
2009-05-15 13:22 ` Jakub Narebski
2009-05-16 5:07 ` Jeff King
0 siblings, 2 replies; 30+ messages in thread
From: Matthias Andree @ 2009-05-15 12:23 UTC (permalink / raw)
To: Jeff King
Cc: Junio C Hamano, git, Alex Riesen, Brandon Casey, Sverre Rabbelier
Am 15.05.2009, 04:02 Uhr, schrieb Jeff King <peff@peff.net>:
>> But what's the new signature or tag good for?
>
> Tagging a tag is good for saying something about the original tag, as
> opposed to saying something about the commit that the original tag
> points to.
Yes, I agree to that since Junio's first reply.
Clear reminder up front: this thread is *not* about tagging tagA with
another tagB (I'll see if git fast-export has issues with that and perhaps
concoct a test script), but this thread *is* about replacing tagA with
itself.
This raises semantic and hence usability concerns.
So let's shift object relations aside for a while, no need to discuss what
we agree about.
Let's narrow down the discussion to signed tag objects (git tag -s/git tag
-u GPG-ID). They are a bit different as there's some extended *meaning*
that lies in the signature. I have no trouble with this. A <--signed-by--
B is implemented by "git tag -s B A."
Your example is:
commit <--signed-by-- tag1 <--signed-by-- tag2.
Tag2 is useful in an "approved by me, too" meaning or similar. Point taken.
If I do "git tag -f -s -m three tag1 tag1" (as opposed to... tag2 tag1),
then I'll have trouble seeing or explaning the meaning or use cases of the
result:
commit <-- signed-by-- NIL (removed) <--signed-by-- tag1.
In this particular corner case (replacing a heaviweight tag object with
itself), tag1 has no meaning, because the tag "destination" gets deleted.
It's as though your luggage trolley disappeared the very moment that you
moved your address label from one handle to the other (presuming it has
one side handle to carry it and one top handle to haul it while on its
wheels). That's just useless. Why do I want to sign the phantom?
For this particular corner case, "git tag -f tag tag" (where I really use
the same tag name twice) could warn along the lines
"Warning: you are trying to replace a tag to [old reference] by a tag to
itself.
However, [old reference] will be removed as per your request,
consequentially, the new tag will reference a deleted [type of old
reference].
If you just want to relocate the tag and want the new tag to point to the
original [type , use git tag -f tagname tagname^{}.
If you really want to create a tag of a tag, add another -f."
Similarly, git tag -d could complain if the tag I'm removing is a tag
object and has children (usually other tags, I believe).
> Arguably the spacing could be more readable (one less blank line between
> the tag header and its message, and an extra space between the message
> and the start of the next header), but I wouldn't call the tag
> inaccessible or removed.
I'd describe the current output as irritating.
> And you can repeat the same exercise with
>
> $ git tag -f -m four tag2 tag2
>
> which will show you the chain of tag2 -> old_tag2 -> tag1 -> commit.
That's the object tree, but not the semantic meaning: semantically,
old_tag2 was supposed to be removed/replaced (tag -d/-f respectively). But
it has to remain in place for syntactic reasons, i. e. to guarantee the
object graph (= syntax) integrity.
And that's what is confusing.
> Right. No ref points to it any more. But that doesn't mean it's not
> there. Just like older commits have no ref pointing to them, and we have
> to give them names based on the refs we do have, like HEAD~5. There is
> not a shorthand syntax for saying "peel exactly N layers of this tag
> chain", but I think that is because nobody has really needed one at this
> point.
That's plausible.
> Going back to your original message, though, it looks like you do have a
> specific problem with fast-export. However, I think it has nothing to do
> with a _renamed_ tag, but in general of tags pointing to tags. The
> outermost tag ends up pointing to a bogus mark of ":0".
>
> I would have thought that would be dealt with by 198246, but I can
> replicate the problem even on the current 'next'. I think we just need
> to be setting a mark for tag objects. The patch below makes your
> fast-export example better, but it still looks like we end up printing
> out one of the tag objects twice.
If fast-import knows how to handle that (by forcibly moving the tag), that
might work.
Thanks for the patch, I'll try it tomorrow and see what I get.
Also thanks for keeping the discussion constructive, rather than fetching
the "troll" punch and dismiss. :-)
> ---
> diff --git a/builtin-fast-export.c b/builtin-fast-export.c
> index 6731713..2349c8d 100644
> --- a/builtin-fast-export.c
> +++ b/builtin-fast-export.c
> @@ -293,6 +293,9 @@ static void handle_tag(const char *name, struct tag
> *tag)
> buf = read_sha1_file(tag->object.sha1, &type, &size);
> if (!buf)
> die ("Could not read tag %s", sha1_to_hex(tag->object.sha1));
> +
> + mark_next_object(&tag->object);
> +
> message = memmem(buf, size, "\n\n", 2);
> if (message) {
> message += 2;
> @@ -335,8 +338,8 @@ static void handle_tag(const char *name, struct tag
> *tag)
> if (!prefixcmp(name, "refs/tags/"))
> name += 10;
> - printf("tag %s\nfrom :%d\n%.*s%sdata %d\n%.*s\n",
> - name, get_object_mark(tag->tagged),
> + printf("tag %s\nmark :%"PRIu32"\nfrom :%d\n%.*s%sdata %d\n%.*s\n",
> + name, last_idnum, get_object_mark(tag->tagged),
> (int)(tagger_end - tagger), tagger,
> tagger == tagger_end ? "" : "\n",
> (int)message_size, (int)message_size, message ? message : "");
--
Matthias Andree
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-15 12:23 ` Matthias Andree
@ 2009-05-15 13:22 ` Jakub Narebski
2009-05-15 14:54 ` Johannes Sixt
2009-05-16 5:07 ` Jeff King
1 sibling, 1 reply; 30+ messages in thread
From: Jakub Narebski @ 2009-05-15 13:22 UTC (permalink / raw)
To: Matthias Andree
Cc: Jeff King, Junio C Hamano, git, Alex Riesen, Brandon Casey,
Sverre Rabbelier
"Matthias Andree" <matthias.andree@gmx.de> writes:
> Am 15.05.2009, 04:02 Uhr, schrieb Jeff King <peff@peff.net>:
>>> But what's the new signature or tag good for?
>>
>> Tagging a tag is good for saying something about the original tag, as
>> opposed to saying something about the commit that the original tag
>> points to.
>
> Yes, I agree to that since Junio's first reply.
>
> Clear reminder up front: this thread is *not* about tagging tagA with
> another tagB (I'll see if git fast-export has issues with that and
> perhaps concoct a test script), but this thread *is* about replacing
> tagA with itself.
>
> This raises semantic and hence usability concerns.
>
> So let's shift object relations aside for a while, no need to discuss
> what we agree about.
>
> Let's narrow down the discussion to signed tag objects (git tag -s/git
> tag -u GPG-ID). They are a bit different as there's some extended
> *meaning* that lies in the signature. I have no trouble with this. A
> <--signed-by--
> B is implemented by "git tag -s B A."
>
> Your example is:
>
> commit <--signed-by-- tag1 <--signed-by-- tag2.
>
> Tag2 is useful in an "approved by me, too" meaning or similar. Point taken.
>
> If I do "git tag -f -s -m three tag1 tag1" (as opposed to... tag2
> tag1), then I'll have trouble seeing or explaning the meaning or use
> cases of the result:
>
> commit <-- signed-by-- NIL (removed) <--signed-by-- tag1.
[...]
> For this particular corner case, "git tag -f tag tag" (where I really
> use the same tag name twice) could warn along the lines [...]
[cut]
THIS IS A FEATURE, NOT A BUG.
Please note that the name of tag (heavyweight tag, i.e. tag object)
is stored in two places: in the tag object itself as a contents of
'tag' header (you can see it in output of "git show <tag>" and also
in output of "git cat-file -p <tag>", where <tag> is heavyweight tag,
e.g. v1.6.3 in git.git repository), and also is default name of tag
reference (reference in "refs/tags/*" namespace) pointing to a tag
object.
So when you create signed tag 'A', you have the following situation
(assuming that it points at some commit)
35805ce <--- 5b7b4ead <=== refs/tags/A
(commit) tag A
(tag)
Please also note that "git tag -f A A" (notice the absence of options
forcing it to be an annotated tag) is a noop - it doesn't change the
situation.
If you do "git tag -f -s A A": note that you _force_ owerwriting a tag
(so git assumes that you know what you are doing), and that one of
-s / -a / -m options is used to force annotated tag (creation of tag
object), you will get the following situation
35805ce <--- 5b7b4ea <--- ada8ddc <=== refs/tags/A
(commit) tag A tag A
(tag) (tag)
What is unclear about this situation? How would you want to change it:
force user to use 'git tag -f -f' (I really know what I am doing)?
Note also that "git show A" would show the whole chain down to the
non-tag object...
Note also that the tag _reference_ (appropriate reference in the
"refs/tags/*" namespace) is purely _local_ matter; what one repository
has in 'refs/tags/v0.1.3', other can have in 'refs/tags/sub/v0.1.3'
for example.
--
Jakub Narebski
Poland
ShadeHawk on #git
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-15 13:22 ` Jakub Narebski
@ 2009-05-15 14:54 ` Johannes Sixt
2009-05-15 15:51 ` Alex Riesen
0 siblings, 1 reply; 30+ messages in thread
From: Johannes Sixt @ 2009-05-15 14:54 UTC (permalink / raw)
To: Jakub Narebski
Cc: Matthias Andree, Jeff King, Junio C Hamano, git, Alex Riesen,
Brandon Casey, Sverre Rabbelier
Jakub Narebski schrieb:
> "Matthias Andree" <matthias.andree@gmx.de> writes:
>> commit <-- signed-by-- NIL (removed) <--signed-by-- tag1.
>
> THIS IS A FEATURE, NOT A BUG.
Please stop it. Everone agrees about this.
Matthias only wants a patch like below. Matthias, if you are serious about
it, please pick this up and turn it into a proper submission. I don't care
enough.
-- Hannes
diff --git a/builtin-tag.c b/builtin-tag.c
index 01e7374..35d39a2 100644
--- a/builtin-tag.c
+++ b/builtin-tag.c
@@ -367,6 +367,7 @@ int cmd_tag(int argc, const char **argv, const char
*prefix)
unsigned char object[20], prev[20];
char ref[PATH_MAX];
const char *object_ref, *tag;
+ struct tag *tag_object;
struct ref_lock *lock;
int annotate = 0, sign = 0, force = 0, lines = -1,
@@ -472,6 +473,15 @@ int cmd_tag(int argc, const char **argv, const char
else if (!force)
die("tag '%s' already exists", tag);
+ if ((tag_object = (struct tag *)parse_object(object)) &&
+ tag_object->object.type == OBJ_TAG &&
+ tag_object->tag &&
+ !strcmp(tag_object->tag, tag)) {
+ error("A tag cannot tag itself. If you meant to tag the commit");
+ error("that the tag refers to, use 'git tag %s %s^{}'.", tag, object_ref);
+ exit(1);
+ }
+
if (annotate)
create_tag(object, tag, &buf, msg.given || msgfile,
sign, prev, object);
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
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
0 siblings, 2 replies; 30+ messages in thread
From: Alex Riesen @ 2009-05-15 15:51 UTC (permalink / raw)
To: Johannes Sixt
Cc: Jakub Narebski, Matthias Andree, Jeff King, Junio C Hamano, git,
Brandon Casey, Sverre Rabbelier
2009/5/15 Johannes Sixt <j.sixt@viscovery.net>:
> Jakub Narebski schrieb:
>> "Matthias Andree" <matthias.andree@gmx.de> writes:
>>> commit <-- signed-by-- NIL (removed) <--signed-by-- tag1.
>>
>> THIS IS A FEATURE, NOT A BUG.
>
> Please stop it. Everone agrees about this.
>
> Matthias only wants a patch like below. Matthias, if you are serious about
> it, please pick this up and turn it into a proper submission. I don't care
> enough.
>
...
> + if ((tag_object = (struct tag *)parse_object(object)) &&
> + tag_object->object.type == OBJ_TAG &&
> + tag_object->tag &&
> + !strcmp(tag_object->tag, tag)) {
> + error("A tag cannot tag itself. If you meant to tag the commit");
If it ever turned into submission, I'll always patch this out. It is stupid.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-14 9:37 ` Matthias Andree
` (2 preceding siblings ...)
2009-05-14 18:22 ` Jeff King
@ 2009-05-15 16:00 ` Daniel Cheng
3 siblings, 0 replies; 30+ messages in thread
From: Daniel Cheng @ 2009-05-15 16:00 UTC (permalink / raw)
To: git
On 14/5/2009 17:37, Matthias Andree wrote:
[...]
> #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.
This show you have no idea how git works internally.
[...]
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-15 15:51 ` Alex Riesen
@ 2009-05-15 16:14 ` Matthias Andree
2009-05-15 16:21 ` Andreas Ericsson
1 sibling, 0 replies; 30+ messages in thread
From: Matthias Andree @ 2009-05-15 16:14 UTC (permalink / raw)
To: Alex Riesen, Johannes Sixt
Cc: Jakub Narebski, Jeff King, Junio C Hamano, git, Brandon Casey,
Sverre Rabbelier
Am 15.05.2009, 17:51 Uhr, schrieb Alex Riesen <raa.lkml@gmail.com>:
> 2009/5/15 Johannes Sixt <j.sixt@viscovery.net>:
>> Jakub Narebski schrieb:
>>> "Matthias Andree" <matthias.andree@gmx.de> writes:
>>>> commit <-- signed-by-- NIL (removed) <--signed-by-- tag1.
>>>
>>> THIS IS A FEATURE, NOT A BUG.
>>
>> Please stop it. Everone agrees about this.
>>
>> Matthias only wants a patch like below. Matthias, if you are serious
>> about it, please pick this up and turn it into a proper submission. I
>> don't care enough.
>>
> ...
>> + if ((tag_object = (struct tag *)parse_object(object)) &&
>> + tag_object->object.type == OBJ_TAG &&
>> + tag_object->tag &&
>> + !strcmp(tag_object->tag, tag)) {
>> + error("A tag cannot tag itself. If you meant to tag the
>> commit");
>
> If it ever turned into submission, I'll always patch this out. It is
> stupid.
I seem to lack intermediate messages, probably queued somewhere, yet I'll
respond already.
Moving a tag on top of itself is just stupid. The result of git -f doesn't
properly match documentation IMO. There is no clear consensus if it's
"gone". It's gone from the refs/ namespace, but kept in the object space,
so there's a split meaning of "replace" or "delete" here.
Arguably, we already need to say -f once, but nothing prevents me from
using git tag -d first and then tag the dangling old_tag1 object to revive
it.
Nobody has shown valid reasons of existence for such tags, or valid
semantics, or use cases.
It's confusing => usability problem => let's put a warning there. I'm not
sure if "error()" is the right function to call here, since I don't have
the full patch to look at.
At any rate, a policy of obstruction is as invalid as anything.
--
Matthias Andree
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
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
1 sibling, 1 reply; 30+ messages in thread
From: Andreas Ericsson @ 2009-05-15 16:21 UTC (permalink / raw)
To: Alex Riesen
Cc: Johannes Sixt, Jakub Narebski, Matthias Andree, Jeff King,
Junio C Hamano, git, Brandon Casey, Sverre Rabbelier
Alex Riesen wrote:
> 2009/5/15 Johannes Sixt <j.sixt@viscovery.net>:
>> Jakub Narebski schrieb:
>>> "Matthias Andree" <matthias.andree@gmx.de> writes:
>>>> commit <-- signed-by-- NIL (removed) <--signed-by-- tag1.
>>> THIS IS A FEATURE, NOT A BUG.
>> Please stop it. Everone agrees about this.
>>
>> Matthias only wants a patch like below. Matthias, if you are serious about
>> it, please pick this up and turn it into a proper submission. I don't care
>> enough.
>>
> ...
>> + if ((tag_object = (struct tag *)parse_object(object)) &&
>> + tag_object->object.type == OBJ_TAG &&
>> + tag_object->tag &&
>> + !strcmp(tag_object->tag, tag)) {
>> + error("A tag cannot tag itself. If you meant to tag the commit");
>
> If it ever turned into submission, I'll always patch this out. It is stupid.
Is it? Does it really make sense to have a tag named "foo" point to a tag object
that in turn points to a tag object without a tag ref? I mean, if you're signing
a tag, it makes sense to want to keep the original tag around so people can
reference it. If you want to *replace* a tag, it doesn't make sense to create
this chain which, iiuc, goes something like this:
tag ref -> tag object -> tag object without ref -> something
Honestly, I can see how this turned out to be confusing, as you end up with a
tag object without a tag, but a new tag in its place. Not to mention that the
new tag won't be push-able without --force in case the old tag was pushed earlier.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
Register now for Nordic Meet on Nagios, June 3-4 in Stockholm
http://nordicmeetonnagios.op5.org/
Considering the successes of the wars on alcohol, poverty, drugs and
terror, I think we should give some serious thought to declaring war
on peace.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-15 16:21 ` Andreas Ericsson
@ 2009-05-15 17:40 ` Junio C Hamano
2009-05-16 7:14 ` Andreas Ericsson
0 siblings, 1 reply; 30+ messages in thread
From: Junio C Hamano @ 2009-05-15 17:40 UTC (permalink / raw)
To: Andreas Ericsson
Cc: Alex Riesen, Johannes Sixt, Jakub Narebski, Matthias Andree,
Jeff King, Junio C Hamano, git, Brandon Casey, Sverre Rabbelier
Andreas Ericsson <ae@op5.se> writes:
> Is it? Does it really make sense to have a tag named "foo" point to a tag object
> that in turn points to a tag object without a tag ref? I mean, if you're signing
> a tag, it makes sense to want to keep the original tag around so people can
> reference it. If you want to *replace* a tag, it doesn't make sense to create
> this chain which, iiuc, goes something like this:
>
> tag ref -> tag object -> tag object without ref -> something
>
> Honestly, I can see how this turned out to be confusing, as you end up with a
> tag object without a tag, but a new tag in its place. Not to mention that the
> new tag won't be push-able without --force in case the old tag was pushed earlier.
Suppose the gpg key used to sign v1.6.3 somehow gets compromised, and I
come up with a new gpg key. I could reassure people that the commit the
old v1.6.3 tagged is genuine if I re-tag with the new key like this:
git tag -f v1.6.3 v1.6.3^{commit}
But what should I do if I would want to reassure people that both the old
v1.6.3 was tagged by _me_ (with the old key that later was compromised)
and that the commit that old tag tags is genuine?
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-15 12:23 ` Matthias Andree
2009-05-15 13:22 ` Jakub Narebski
@ 2009-05-16 5:07 ` Jeff King
1 sibling, 0 replies; 30+ messages in thread
From: Jeff King @ 2009-05-16 5:07 UTC (permalink / raw)
To: Matthias Andree
Cc: Junio C Hamano, git, Alex Riesen, Brandon Casey, Sverre Rabbelier
On Fri, May 15, 2009 at 02:23:33PM +0200, Matthias Andree wrote:
> Clear reminder up front: this thread is *not* about tagging tagA with
> another tagB (I'll see if git fast-export has issues with that and perhaps
> concoct a test script), but this thread *is* about replacing tagA with
> itself.
I'm pretty sure git fast-export does have a problem just with tags of
tags; that was what I was looking at fixing with the patch in my
previous mail.
> If I do "git tag -f -s -m three tag1 tag1" (as opposed to... tag2 tag1),
> then I'll have trouble seeing or explaning the meaning or use cases of the
> result:
>
> commit <-- signed-by-- NIL (removed) <--signed-by-- tag1.
I think this is where we diverge. Removing a ref to an object (in my
mental model) doesn't make it "NIL" or "removed". It simply does not
have a direct name anymore.
Now, you _will_ have problems rewriting your tags all of the time,
because (IIRC) git does not fetch tags that it already has. So anybody
fetching from you will not ever see the new tag. But that is a problem
with _any_ tag overwriting, not just overwriting with a tag chain. And
that is why such overwriting is protected by "-f".
> In this particular corner case (replacing a heaviweight tag object with
> itself), tag1 has no meaning, because the tag "destination" gets deleted.
> It's as though your luggage trolley disappeared the very moment that you
> moved your address label from one handle to the other (presuming it has
> one side handle to carry it and one top handle to haul it while on its
> wheels). That's just useless. Why do I want to sign the phantom?
Again, I disagree that it is a phantom. It is now a link in a chain of
signatures. The head of the chain has a name, but that doesn't mean
every link needs to.
So I think the reason that you are seeing "there is no bug, it is a
feature" responses from git people is that we have a different mental
model of what is going on. I don't know whether that means your model is
_wrong_, or simply _different_.
> For this particular corner case, "git tag -f tag tag" (where I really use
> the same tag name twice) could warn along the lines
>
> "Warning: you are trying to replace a tag to [old reference] by a tag to
> itself.
> However, [old reference] will be removed as per your request,
> consequentially, the new tag will reference a deleted [type of old
> reference].
> If you just want to relocate the tag and want the new tag to point to the
> original [type , use git tag -f tagname tagname^{}.
> If you really want to create a tag of a tag, add another -f."
I am torn on whether such a warning is a good idea. Yes, it can prevent
a user from shooting themselves in the foot. But it also is something
you may legitimately want to be doing, and having git yell at you is a
bad thing (and I actually do disagree with some of the wording, but I
think the real point in contention is whether this should be flagged as
a dangerous and potentially wrong operation).
Your original problem seemed to come from thinking that "git tag -f tag
tag" would "redo" the tagging (when what you really wanted was "git tag
-f tag tag^{commit}"). I wonder if it would be helpful to provide a more
obvious and constructive way of doing that, like
git tag --amend tag
The benefits would be:
- it is a more natural way of saying what you want to do, and it
mirrors the "git commit --amend" command
- it could also populate the editor with the original tag message,
which is probably useful if you are trying to fix up any issues.
The obvious drawback to me is that it might encourage rewriting commits,
which is something that it is not really sane to do after they have been
published (of course, we already encourage rewriting _commits_ via
--amend, which have similar if somewhat lesser problems).
And of course it doesn't actually _solve_ the problem you mentioned, it
merely makes it more likely that the user will see our handy safe
version and not use the error-prone "git tag -f" version. So maybe that
is good enough and maybe not.
> Similarly, git tag -d could complain if the tag I'm removing is a tag
> object and has children (usually other tags, I believe).
I'm not sure what you mean here. Why would removing a tag to a tag to a
commit be any more or less dangerous than removing a tag to a commit?
>> Arguably the spacing could be more readable (one less blank line between
>> the tag header and its message, and an extra space between the message
>> and the start of the next header), but I wouldn't call the tag
>> inaccessible or removed.
>
> I'd describe the current output as irritating.
Agreed, though it really has nothing to do with the issue at hand. Even
a tag to a commit looks ugly (try, e.g., "git show v1.6.2.1" in the git
repo -- extra space before the tag text, no space between the PGP
signature and the commit).
>> And you can repeat the same exercise with
>>
>> $ git tag -f -m four tag2 tag2
>>
>> which will show you the chain of tag2 -> old_tag2 -> tag1 -> commit.
>
> That's the object tree, but not the semantic meaning: semantically,
> old_tag2 was supposed to be removed/replaced (tag -d/-f respectively). But
> it has to remain in place for syntactic reasons, i. e. to guarantee the
> object graph (= syntax) integrity.
> And that's what is confusing.
Again, I think "semantic meaning" here is in the eye of the beholder.
The intended semantics are not "make tag2 a tag to tag2" but
"dereference what is currently named tag2, and make tag2 a tag to that".
So what happens makes sense under that mental model.
>> I would have thought that would be dealt with by 198246, but I can
>> replicate the problem even on the current 'next'. I think we just need
>> to be setting a mark for tag objects. The patch below makes your
>> fast-export example better, but it still looks like we end up printing
>> out one of the tag objects twice.
>
> If fast-import knows how to handle that (by forcibly moving the tag), that
> might work.
I don't think it needs to forcibly move the tag. The fast-export output
contains two "tag" stanzas, but those are only about creating the tag
objects themselves. The actual ref is set only once with lines like:
reset refs/tags/foo
from :2
At least that is my quick reading of the output; I admit I am not much
of a fast-export/import person, so there may be something subtle I am
missing.
> Also thanks for keeping the discussion constructive, rather than fetching
> the "troll" punch and dismiss. :-)
Well, I _do_ like a good flamefest... ;)
-Peff
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
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 17:16 ` Junio C Hamano
0 siblings, 2 replies; 30+ messages in thread
From: Andreas Ericsson @ 2009-05-16 7:14 UTC (permalink / raw)
To: Junio C Hamano
Cc: Alex Riesen, Johannes Sixt, Jakub Narebski, Matthias Andree,
Jeff King, git, Brandon Casey, Sverre Rabbelier
Junio C Hamano wrote:
> Andreas Ericsson <ae@op5.se> writes:
>
>> Is it? Does it really make sense to have a tag named "foo" point to a tag object
>> that in turn points to a tag object without a tag ref? I mean, if you're signing
>> a tag, it makes sense to want to keep the original tag around so people can
>> reference it. If you want to *replace* a tag, it doesn't make sense to create
>> this chain which, iiuc, goes something like this:
>>
>> tag ref -> tag object -> tag object without ref -> something
>>
>> Honestly, I can see how this turned out to be confusing, as you end up with a
>> tag object without a tag, but a new tag in its place. Not to mention that the
>> new tag won't be push-able without --force in case the old tag was pushed earlier.
>
> Suppose the gpg key used to sign v1.6.3 somehow gets compromised, and I
> come up with a new gpg key. I could reassure people that the commit the
> old v1.6.3 tagged is genuine if I re-tag with the new key like this:
>
> git tag -f v1.6.3 v1.6.3^{commit}
>
> But what should I do if I would want to reassure people that both the old
> v1.6.3 was tagged by _me_ (with the old key that later was compromised)
> and that the commit that old tag tags is genuine?
>
Add a tag with a new name, pointing to the original tag. Try doing what
Matthias did and then run "git show $tagname". It won't show the original
tag at all, so people have to resort to low-level commands in order to
see it, but it will still exist as an object.
The main point though is that re-creating a ref with different content
adds major headaches when distributing it. People who have the old tag
and fetches from a new repo won't get the new tag stored in a ref. If
the object is transferred, it will be garbage-collected.
So let's examine the scenario you described, with your gpg key being
compromised.
You re-create all your tag refs with same-name tags that point to the
old tags.
Joe Dev fetches from you, but your tags do not get stored as refs.
Joe Dev publishes a repo somewhere with a bunch of topic-branches and
requests you merge from those repositories.
You fetch from Joe.
Now we have two opposite problems.
If tags aren't updated when Joe Dev fetches from you, his refs will
not match yours when you fetch from him, and anyone cloning from him
even after the re-sign will never get the new tags at all.
If tag refs *do* get updated when fetching from a repo when we already
have another tag ref with the same name, you fetching from Joe Dev
could undo all your re-created tags and make the new tag-objects
garbage-collectable. This assumes Joe Dev published his repo before
fetching your new tags though.
Perhaps I'm missing something. It's 9AM here and I woke up ten minutes
ago, but it seems to me that what will happen and what should happen
is not entirely clear when one creates tag refs that already exist and
are published.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
Register now for Nordic Meet on Nagios, June 3-4 in Stockholm
http://nordicmeetonnagios.op5.org/
Considering the successes of the wars on alcohol, poverty, drugs and
terror, I think we should give some serious thought to declaring war
on peace.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
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
1 sibling, 1 reply; 30+ messages in thread
From: Jakub Narebski @ 2009-05-16 7:56 UTC (permalink / raw)
To: Andreas Ericsson
Cc: Junio C Hamano, Alex Riesen, Johannes Sixt, Matthias Andree,
Jeff King, git, Brandon Casey, Sverre Rabbelier
On Sat, 16 May 2009, Andreas Ericsson wrote:
> Add a tag with a new name, pointing to the original tag. Try doing what
> Matthias did and then run "git show $tagname". It won't show the original
> tag at all, so people have to resort to low-level commands in order to
> see it, but it will still exist as an object.
Not true. Did you check that?
"git show <tag>" shows the whole chain of objects down to non-tag object.
tag tag1
Tagger: Jakub Narebski <jnareb@gmail.com>
Date: Sat May 16 09:55:13 2009 +0200
tag1 (retagged)
tag tag1
Tagger: Jakub Narebski <jnareb@gmail.com>
Date: Sat May 16 09:54:58 2009 +0200
tag1
commit 6d3eee4f5e9fde51f3213320b98bda5f325000e4
[...]
True, the separation between objects could have been made more explicit...
--
Jakub Narebski
Poland
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-16 7:56 ` Jakub Narebski
@ 2009-05-16 8:02 ` Andreas Ericsson
0 siblings, 0 replies; 30+ messages in thread
From: Andreas Ericsson @ 2009-05-16 8:02 UTC (permalink / raw)
To: Jakub Narebski
Cc: Junio C Hamano, Alex Riesen, Johannes Sixt, Matthias Andree,
Jeff King, git, Brandon Casey, Sverre Rabbelier
Jakub Narebski wrote:
> On Sat, 16 May 2009, Andreas Ericsson wrote:
>
>> Add a tag with a new name, pointing to the original tag. Try doing what
>> Matthias did and then run "git show $tagname". It won't show the original
>> tag at all, so people have to resort to low-level commands in order to
>> see it, but it will still exist as an object.
>
> Not true. Did you check that?
>
Yes, but with light-weight tags on a repo after cvs import. Mea culpa, so
this is a non-issue. Thanks for politely pointing out my error :-)
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
Register now for Nordic Meet on Nagios, June 3-4 in Stockholm
http://nordicmeetonnagios.op5.org/
Considering the successes of the wars on alcohol, poverty, drugs and
terror, I think we should give some serious thought to declaring war
on peace.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-16 7:14 ` Andreas Ericsson
2009-05-16 7:56 ` Jakub Narebski
@ 2009-05-16 17:16 ` Junio C Hamano
2009-05-19 11:21 ` Matthias Andree
1 sibling, 1 reply; 30+ messages in thread
From: Junio C Hamano @ 2009-05-16 17:16 UTC (permalink / raw)
To: Andreas Ericsson
Cc: Alex Riesen, Johannes Sixt, Jakub Narebski, Matthias Andree,
Jeff King, git, Brandon Casey, Sverre Rabbelier
Andreas Ericsson <ae@op5.se> writes:
> You re-create all your tag refs with same-name tags that point to the
> old tags.
> Joe Dev fetches from you, but your tags do not get stored as refs.
> Joe Dev publishes a repo somewhere with a bunch of topic-branches and
> requests you merge from those repositories.
> You fetch from Joe.
>
> Now we have two opposite problems.
> If tags aren't updated when Joe Dev fetches from you, his refs will
> not match yours when you fetch from him, and anyone cloning from him
> even after the re-sign will never get the new tags at all.
> If tag refs *do* get updated when fetching from a repo when we already
> have another tag ref with the same name, you fetching from Joe Dev
> could undo all your re-created tags and make the new tag-objects
> garbage-collectable. This assumes Joe Dev published his repo before
> fetching your new tags though.
>
> Perhaps I'm missing something....
No, you did not miss anything. It illustrates the problem space very
well.
There are two "names" to a tag. The name of a tag is recorded in the
object itself, in its "tag" header.
$ git cat-file tag v1.6.3
object f01f1099f40f24fe6f7802185340a6fa3a3d4f35
type commit
tag v1.6.3
tagger Junio C Hamano <gitster@pobox.com> 1241659007 -0700
GIT 1.6.3
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
...
Anybody can forge, even down to the trailing signature part with a
compromised key, such a tag object that claims to be "tag v1.6.3" and
point anything with it.
But the "name" you usually access a tag object with is not this one.
Instead, you use the name of the ref in refs/tags hierarchy. These two
names are supposed to match by convention, and I think recent fsck even
checks it.
Unlike the name recorded in tag objects, you can have only one v1.6.3 in
your ref namespace. And the way git protects users from maliciously made
tags has been by not re-fetching what already exist unless explicitly
asked. The consequence of this is that you somehow obtained a forged or
vulnerable one first, you will not get corrected ones automatically.
But that is a feature in the current set-up.
If the key that signs release tags were compromised and the tags got
re-signed with a new key (whether I re-tag by pointing at the commit
objects, or pointing at the old-genuine tag objects), that fact needs to
be advertised ("Sorry, but I had to re-tag; if you have old tags, please
re-fetch"), and the user who is currently protected by this "no automatic
re-fetching" mechanism has to somehow assert that "Sorry" is really from
me, and allow git to re-fetch.
The workflow for a such case would be:
(0) I notice the signing key was somehow compromised; roll a new key,
re-sign the tags, and send out a "I had to re-tag, and here is a list
of the old and new tag object names you can use to verify" message;
(1) You read such a message, You do "git for-each-ref refs/tags" to see
the object names to check with my message, and realize that you have
stale tags. So does Joe Dev but he may be slower to react;
(2) You fetch (or ls-remote) from Joe Dev which is your preferrerd mirror
of my tree and notice he hasn't updated, and let him know. In the
meantime you fetch "git fetch --tags" from me, and verify the result
against my message.
(3) Joe Dev would do the same.
That's largely manual, cumbersome, and makes everybody involved painfully
aware of what is going on, which may be an advantage over silently
updating with a new tag without telling anybody.
But you can improve the situation without losing security by doing
something like this.
* Introduce a concept of "trusted signing keys" (similar to the way
distros sign their binary packages), whose fingerprints are probably
stored in .git/config of the receiving repositories;
* Upon 'git tag -v <name>', verify that the signature was made with one
of the trusted signing keys;
* Inside 'git fetch':
- before starting to fetch, see if there are signed tags that exist
locally but not signed with any of the trusted keys;
- for the signed tags we find in the above step, if the remote end has
different tag object at the same refname, ask for them;
- perform the main 'git fetch' transfer and store things according to
the refspec as usual (but do not store the tags re-fetched only
because of the new logic yet);
- for the tags re-fetched with the new logic, see if they are signed by
trusted keys, and if so replace the stale tags with them.
The step (0) to issue a "Sorry but I had to re-tag" message with "here is
the fingerprint of new signing key" is still necessary, and you need to
react to it by replacing the old trusted signing key with the fingerprint
of the new key, but after that everything can be made automatic.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-16 17:16 ` Junio C Hamano
@ 2009-05-19 11:21 ` Matthias Andree
2009-05-19 11:29 ` Jeff King
0 siblings, 1 reply; 30+ messages in thread
From: Matthias Andree @ 2009-05-19 11:21 UTC (permalink / raw)
To: Junio C Hamano, Andreas Ericsson
Cc: Alex Riesen, Johannes Sixt, Jakub Narebski, Jeff King, git,
Brandon Casey, Sverre Rabbelier
Am 16.05.2009, 19:16 Uhr, schrieb Junio C Hamano <gitster@pobox.com>:
> The workflow for a such case would be:
>
> (0) I notice the signing key was somehow compromised; roll a new key,
> re-sign the tags, and send out a "I had to re-tag, and here is a
> list
> of the old and new tag object names you can use to verify" message;
>
> (1) You read such a message, You do "git for-each-ref refs/tags" to see
> the object names to check with my message, and realize that you have
> stale tags. So does Joe Dev but he may be slower to react;
>
> (2) You fetch (or ls-remote) from Joe Dev which is your preferrerd
> mirror
> of my tree and notice he hasn't updated, and let him know. In the
> meantime you fetch "git fetch --tags" from me, and verify the result
> against my message.
>
> (3) Joe Dev would do the same.
>
> That's largely manual, cumbersome, and makes everybody involved painfully
> aware of what is going on, which may be an advantage over silently
> updating with a new tag without telling anybody.
>
> But you can improve the situation without losing security by doing
> something like this.
Let's do things step by step and fix the current issue - and I fear there
won't be an easy technical solution, so let's amend to the documentation
for the nonce.
OK, what I was trying to do is rewrite history to fix up some b0rked
internal addresses. That's a repository for a mostly frozen project, which
is more a reference point than a basis for development. I had to recreate
the few tag signatures they were, and hence I used "git tag -f" without
thinking too much. I had seen the section on re-tagging, and am aware of
it, but it somehow didn't apply to my situation.
I think we ought
(1) to fix the git tag -h output and manual page for consistency, and
(2) to add a note to make users aware that they can also tag tags (the
[<object>] in SYNOPSIS may not be hint enough, as Git seems to differ
substantially from other SCM systems in this respect - so this is a
usability concern that deserves documentation).
I'll suggest something, but that can take a couple of days.
What else can we tag in Git? Commits and Tags. Is it sensible and does it
work to tag blobs or trees?
--
Matthias Andree
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: git-tag bug? confusing git fast-export with double tag objects
2009-05-19 11:21 ` Matthias Andree
@ 2009-05-19 11:29 ` Jeff King
0 siblings, 0 replies; 30+ messages in thread
From: Jeff King @ 2009-05-19 11:29 UTC (permalink / raw)
To: Matthias Andree
Cc: Junio C Hamano, Andreas Ericsson, Alex Riesen, Johannes Sixt,
Jakub Narebski, git, Brandon Casey, Sverre Rabbelier
On Tue, May 19, 2009 at 01:21:58PM +0200, Matthias Andree wrote:
> What else can we tag in Git? Commits and Tags. Is it sensible and does it
> work to tag blobs or trees?
A tagged blob:
$ cd git && git show junio-gpg-pub | sed '/^--/Q'
tag junio-gpg-pub
Tagger: Junio C Hamano <junkio@cox.net>
Date: Tue Dec 13 16:33:29 2005 -0800
GPG key to sign git.git archive.
This blob object contains the GPG public key I use to sign git.git
archive.
To use it to verify tags I signed, do:
$ git-cat-file blob junio-gpg-pub | gpg --import
to import it into your keyring, and then
$ git-verify-tag $tag_to_be_verified
A tagged tree:
$ cd linux-2.6 && git show v2.6.11 | sed '/^--/Q'
tag v2.6.11-tree
This is the 2.6.11 tree object.
NOTE! There's no commit for this, since it happened before I started with git.
Eventually we'll import some sort of history, and that should tie this tree
object up to a real commit. In the meantime, this acts as an anchor point for
doing diffs etc under git.
-Peff
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2009-05-19 11:29 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
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
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).