threads / discuss / 47153

Unify annotated and non-annotated tags

Subject: Unify annotated and non-annotated tags

## tl;dr

6 messages between Nov 10, 2017 and Dec 23, 2017.

replies: 5people: 3as markdown or json

anatoly techtonik· Nov 10, 2017, 10:58 UTC · lore
Hi,

It is hard to work with Git tags, because on low level hash of non-annotated tag is pointing to commit, but hash for annotated tag is pointing to tag metadata.

On low level that means that there is no way to get commit hash from tag in a single step. If tag is annotated, you need to find and parse ^{} string of show-ref, if not, then look for string without ^{}.

So, why not just make all tags work the same so that every tag has its own hash and you need to dereference it in the same way to get commit hash?

This way I could get all commit hashes with just:
    git show-ref --tags -d | grep "\^{}"
or abandon ^{} completely and show commit hashes on -d:
    git show-ref --tags --dereference
-- 
anatoly t.
Igor Djordjevic· Nov 11, 2017, 01:46 UTC · re: anatoly techtonik · lore

Re: Unify annotated and non-annotated tags

Hi Anatoly,
On 10/11/2017 11:58, anatoly techtonik wrote:
Show 8 quoted lines
> It is hard to work with Git tags, because on low level hash
> of non-annotated tag is pointing to commit, but hash for
> annotated tag is pointing to tag metadata.
> 
> On low level that means that there is no way to get commit
> hash from tag in a single step. If tag is annotated, you need
> to find and parse ^{} string of show-ref, if not, then look for
> string without ^{}.

That is not quite true, as you can always dereference any tag (annotated or not) using "<tag>^0" notation, see git-rev-parse[1]:

  "As a special rule, <rev>^0 means the commit itself and is used when 
  <rev> is the object name of a tag object that refers to a commit 
  object."
 
Show 12 quoted lines
> So, why not just make all tags work the same so that every
> tag has its own hash and you need to dereference it in the
> same way to get commit hash?
> 
> This way I could get all commit hashes with just:
> 
>     git show-ref --tags -d | grep "\^{}"
> 
> or abandon ^{} completely and show commit hashes on -d:
> 
>     git show-ref --tags --dereference
>

Depending on what you would _exactly_ like to do, you could get all tagged commit hashes like this:

	git rev-list --tags --no-walk

Note that each commit will be listed only once, even if more tags (annotated or not) point to it.

If you would like to mimic output of "git show-ref", repeating commits for each tag pointing to it and showing full tag name as well, you could do something like this, for example:

	for tag in $(git for-each-ref --format="%(refname)" refs/tags)
	do
		printf '%s %s\n' "$(git rev-parse $tag^0)" "$tag"
	done
Hope that helps a bit.
Regards, Buga
[1] https://git-scm.com/docs/git-rev-parse#git-rev-parse-emltrevgtemegemHEADv1510em
Junio C Hamano· Nov 11, 2017, 02:06 UTC · re: Igor Djordjevic · lore

Re: Unify annotated and non-annotated tags

Igor Djordjevic <igor.d.djordjevic@gmail.com> writes:
Show 11 quoted lines
> If you would like to mimic output of "git show-ref", repeating 
> commits for each tag pointing to it and showing full tag name as 
> well, you could do something like this, for example:
>
> 	for tag in $(git for-each-ref --format="%(refname)" refs/tags)
> 	do
> 		printf '%s %s\n' "$(git rev-parse $tag^0)" "$tag"
> 	done
>
>
> Hope that helps a bit.

If you use for-each-ref's --format option, you could do something like (pardon a long line):

git for-each-ref --format='%(if)%(*objectname)%(then)%(*objectname)%(else)%(objectname)%(end) %(refname)' refs/tags
without any loop, I would think.
Igor Djordjevic· Nov 11, 2017, 02:50 UTC · re: Junio C Hamano · lore

Re: Unify annotated and non-annotated tags

On 11/11/2017 03:06, Junio C Hamano wrote:
Show 20 quoted lines
> Igor Djordjevic <igor.d.djordjevic@gmail.com> writes:
> 
>> If you would like to mimic output of "git show-ref", repeating 
>> commits for each tag pointing to it and showing full tag name as 
>> well, you could do something like this, for example:
>>
>> 	for tag in $(git for-each-ref --format="%(refname)" refs/tags)
>> 	do
>> 		printf '%s %s\n' "$(git rev-parse $tag^0)" "$tag"
>> 	done
>>
>>
>> Hope that helps a bit.
> 
> If you use for-each-ref's --format option, you could do something
> like (pardon a long line):
> 
> git for-each-ref --format='%(if)%(*objectname)%(then)%(*objectname)%(else)%(objectname)%(end) %(refname)' refs/tags
> 
> without any loop, I would think.

... and I did have a feeling it should be possible in a single Git command :P Thanks.

anatoly techtonik· Nov 23, 2017, 07:31 UTC · re: Junio C Hamano · lore

Re: Unify annotated and non-annotated tags

On Sat, Nov 11, 2017 at 5:06 AM, Junio C Hamano <gitster@pobox.com> wrote:
Show 20 quoted lines
> Igor Djordjevic <igor.d.djordjevic@gmail.com> writes:
>
>> If you would like to mimic output of "git show-ref", repeating
>> commits for each tag pointing to it and showing full tag name as
>> well, you could do something like this, for example:
>>
>>       for tag in $(git for-each-ref --format="%(refname)" refs/tags)
>>       do
>>               printf '%s %s\n' "$(git rev-parse $tag^0)" "$tag"
>>       done
>>
>>
>> Hope that helps a bit.
>
> If you use for-each-ref's --format option, you could do something
> like (pardon a long line):
>
> git for-each-ref --format='%(if)%(*objectname)%(then)%(*objectname)%(else)%(objectname)%(end) %(refname)' refs/tags
>
> without any loop, I would think.
Thanks. That helps.

So my proposal is to get rid of non-annotated tags, so to get all tags with commits that they point to, one would use:

git for-each-ref --format='%(*objectname) %(refname)' refs/tags

For so-called non-annotated tags just leave the message empty. I don't see why anyone would need non-annotated tags though.

-- 
anatoly t.
anatoly techtonik· Dec 23, 2017, 13:33 UTC · re: Junio C Hamano · lore

Re: Unify annotated and non-annotated tags

On Sat, Nov 11, 2017 at 5:06 AM, Junio C Hamano <gitster@pobox.com> wrote:
Show 20 quoted lines
> Igor Djordjevic <igor.d.djordjevic@gmail.com> writes:
>
>> If you would like to mimic output of "git show-ref", repeating
>> commits for each tag pointing to it and showing full tag name as
>> well, you could do something like this, for example:
>>
>>       for tag in $(git for-each-ref --format="%(refname)" refs/tags)
>>       do
>>               printf '%s %s\n' "$(git rev-parse $tag^0)" "$tag"
>>       done
>>
>>
>> Hope that helps a bit.
>
> If you use for-each-ref's --format option, you could do something
> like (pardon a long line):
>
> git for-each-ref --format='%(if)%(*objectname)%(then)%(*objectname)%(else)%(objectname)%(end) %(refname)' refs/tags
>
> without any loop, I would think.

This doesn't work with git 1.9.1 https://github.com/rtfd/readthedocs.org/pull/3441#issuecomment-353567756 When it was added? I searched through GitHub and docs, but can't find any historical records.

-- 
anatoly t.

← back to recent threads