开发者

How to tell which commit a tag points to in Git?

I have a bunch of unannotated tags in the repository and I want to work out which commit they point to. Is there a command that that will just list the tags and their commit SHAs? Checking out the tag and looking at the HEAD seems a bit too laborious to me.

Update

I realized after I went through the responses that what I actually wanted was to simply look at the history leading up to the tag, for which g开发者_运维技巧it log <tagname> is sufficient.

The answer that is marked as answer is useful for getting a list of tags and their commits, which is what I asked. With a bit of shell hackery I'm sure it's possible to transform those into SHA+Commit message.


One way to do this would be with git rev-list. The following will output the commit to which a tag points:

$ git rev-list -n 1 $TAG

NOTE This works for both Annotated and Unannotated tags

You could add it as an alias in ~/.gitconfig if you use it a lot:

[alias]
  tagcommit = rev-list -n 1

And then call it with:

$ git tagcommit $TAG

Possible pitfall: if you have a local checkout or a branch of the same tag name, this solution might get you "warning: refname 'myTag' is ambiguous". In that case, try increasing specificity, e.g.:

$ git rev-list -n 1 tags/$TAG


WARNING This only works for Unannotated tags Therefore it is safer to use the accepted answer which works in the general case https://stackoverflow.com/a/1862542/1586965

git show-ref --tags

For example, git show-ref --abbrev=7 --tags will show you something like the following:

f727215 refs/tags/v2.16.0
56072ac refs/tags/v2.17.0
b670805 refs/tags/v2.17.1
250ed01 refs/tags/v2.17.2


Just use git show <tag>

However, it also dumps commit diffs. To omit those diffs, use git log -1 <tag>. (Thanks to @DolphinDream and @demisx !)


From Igor Zevaka:

Summary

Since there are about 4 almost equally acceptable yet different answers I will summarise all the different ways to skin a tag.

  1. git rev-list -1 $TAG (answer). git rev-list outputs the commits that lead up to the $TAG similar to git log but only showing the SHA1 of the commit. The -1 limits the output to the commit it points at.

  2. git show-ref --tags (answer) will show all tags (local and fetched from remote) and their SHA1s.

  3. git show-ref $TAG (answer) will show the tag and its path along with the SHA1.

  4. git rev-parse $TAG (answer) will show the SHA1 of an unannotated tag.

  5. git rev-parse --verify $TAG^{commit} (answer) will show a SHA1 of both annotated and unannotated tags. On Windows use git rev-parse --verify %TAG%^^^^{commit} (four hats).

  6. cat .git/refs/tags/* or cat .git/packed-refs (answer) depending on whether or not the tag is local or fetched from remote.


For annotated tags, git show-ref TAG shows the tag's hash, not the hash of the commit it points to.

git show-ref --dereference TAG shows, additionally, the commit being pointed at with an added ^{}.


Use

git rev-parse --verify <tag>^{commit}

(which would return SHA-1 of a commit even for annotated tag).


git show-ref <tag> would also work if <tag> is not annotated. And there is always git for-each-ref (see documentation for details).


How about this:

git log -1 $TAGNAME

OR

git log -1 origin/$TAGNAME


In order to get the sha/hash of the commit that a tag refers to (not the sha of the tag):

git rev-list -1 <tag>


Short post-Git-2 answer

I know this question has been out here for quite a while. And the answer from CB Bailey is 100% correct: git show-ref --tags --abbrev

I like this one better since it uses git tag:

git tag --list --format '%(refname:short) %(objectname:short)'

Simple. Short.

PS alias it as git taglist with this command:

git config --global alias.taglist "tag --list --format '%(refname:short) %(objectname:short)'"


I'd also like to know the "right" way, but in the meantime, you can do this:

git show mytag | head -1    


Even though this is pretty old, I thought I would point out a cool feature I just found for listing tags with commits:

git log --decorate=full

It will show the branches which end/start at a commit, and the tags for commits.


You could as well get more easy-to-interpret picture of where tags point to using

git log --graph |git name-rev --stdin --tags |less

and then scroll to the tag you're looking for via /.

More compact view (--pretty=oneline) plus all heads (-a) could also help:

git log -a --pretty=oneline --graph |git name-rev --stdin --tags |less

Looks a bit terrifying, but could also be aliased in ~/.gitconfig if necessary.

~/.gitconfig

[alias]
ls-tags = !git log -a --pretty=oneline --graph |git name-rev --stdin --tags |less


The --format option can be used to show both tag hash and the commit hash, and to distinguish between lightweight and annotated tags.

git tag --format="%(color:bold cyan)== %(refname:short) ==%(if)%(object)%(then)%0aTag Hash: %(objectname)%0aTag Date: %(taggerdate:iso-local)%0a  Commit: %(object) %0a%0a%(contents)%(else)%0a(lightweight tag)%0a  Commit: %(objectname)%(end)%0a"

Gives output similar to:

== b2lightweight ==
(lightweight tag)
  Commit: 0450fae4352dbbbf088419757eda32711316a02e

== c3_annotated ==
Tag Hash: 19961d8678a09a319a9d6c398c79f27cc23d610c
Tag Date: 2021-08-06 15:18:48 -0600
  Commit: 85be6e80c109ce44d78f0ca0da8e1ec53817b24c

This is my tag message.

It has multiple lines.

Another line.

To define as a git alias, you can edit the global git config with git config --global -e and add the following:

[alias]
    tag-verbose = tag --format='%(color:bold cyan)== %(refname:short) ==%(if)%(object)%(then)%0aTag Hash: %(objectname)%0aTag Date: %(taggerdate:iso-local)%0a  Commit: %(object) %0a%0a%(contents)%(else)%0a(lightweight tag)%0a  Commit: %(objectname)%(end)%0a'

The alias still allows filtering, e.g.

C:\playground>git tag-verbose -l *b2*
== b2lightweight ==
(lightweight tag)
  Commit: 0450fae4352dbbbf088419757eda32711316a02e

For additional information on the --format options see the "Field Names" section under git help for-each-ref. (git help tag states "The format is the same as that of git-for-each-ref")


This doesn't show the filenames, but at least you get a feel of the repository.

cat .git/refs/tags/*

Each file in that directory contains a commit SHA pointing to a commit.


From git mailing list, here is the way to get the list of commit hashes for tags with automatic dereferencing for annotated tags:

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


i'd also like to know the right way, but you can always peek either into:

$ cat .git/packed-refs 

or:

$ cat .git/refs/tags/*


This will get you the current SHA1 hash

Abbreviated Commit Hash

git show <tag> --format="%h" --> 42e646e

Commit Hash

git show <tag> --format="%H" --> 42e646ea3483e156c58cf68925545fffaf4fb280


If you would like to see the details of the tag SOMETAG (tagger, date, etc), the hash of the commit it points to and a bit of info about the commit but without the full diff, try

git show --name-status SOMETAG

Example output:

tag SOMETAG
Tagger: ....
Date:   Thu Jan 26 17:40:53 2017 +0100

 .... tag message .......

commit 9f00ce27c924c7e972e96be7392918b826a3fad9
Author: .............
Date:   Thu Jan 26 17:38:35 2017 +0100

 .... commit message .......

..... list of changed files with their change-status (like git log --name-status) .....


So I have a load of release folders, where those folders may be checked out from one of a few different repos, and may be dev, qa or master branches or may be production releases, checked out from a tag, and the tag may be annotated or not. I have a script that will look at the target folder and get be back an answer in the form -. The problem is different versions of git return different status' for a tag checkout.

So I found git show-ref --tags worked initially, except for the annotated tags. However adding -d added a separate entry to the list of tags, one for the tag, the other for the annotation (the annotation commit was identified as ^{} which I stripped out with sed).

So this is the core of my script, for anyone that wants it:-

REPO=`git --git-dir=${TARGET} remote show origin -n | \
         grep "Fetch URL:" | \
         sed -E "s/^.*\/(.*)$/\1/" | \
         sed "s/.git$//"`

TAG=`git --git-dir=${TARGET} show-ref -d --tags | \
         grep \`git --git-dir=${TARGET} show --quiet --format=format:%H HEAD\` | \
         cut -d\  -f2 | \
         cut -d/ -f3 | \
         sed "s/\^{}$//"`

if [ "${TAG}" == "" ] ; then 
  BRANCH=`git --git-dir=${TARGET} show-ref --heads | \
         grep \`git --git-dir=${TARGET} show --quiet --format=format:%H HEAD\` | \
         cut -d\  -f2 | \
         cut -d/ -f3`
  TAG=${BRANCH}
fi


Can use below, It will give the commit hash
git show -s --format=%H <tag>^{commit}

If abbreviated commit hash required, git show -s --format=%h <tag>^{commit}


Hacky solution

Parse the .git/packed-refs and format it as {tag}\t{sha}

sed -n '/ refs\/tags/ { s@\([^ ]*\) refs/tags/\(.*\)@\2\t\1@; p}' .git/packed-refs


git rev-list --no-walk = git rev-parse git rev-parse [tag_name]

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜