How can I list tags contained by a given branch, the opposite of:
git tag --contains <commit>
Which "only list tags which contain the specified commit".
If something like this does not exist, how do I test whether a commit is contained by another commit so that I can script this?
I could do this:开发者_如何转开发
commit=$(git rev-parse $branch)
for tag in $(git tag)
do
git log --pretty=%H $tag | grep -q -E "^$commit$"
done
But I hope there is a better way as this might take a long time in a repository with many tags and commits.
git tag --merged <branch>
From the man page:
--[no-]merged <commit>
Only list tags whose tips are reachable, or not reachable if --no-merged is used, from the specified commit (HEAD if not specified).
I believe this option was added quite recently - it definitely wasn't available back when the original question was posed and the above answers suggested. Since this thread is still the first hit in Google for the question I figured I'd throw it in for anyone who scrolls down to the bottom looking for an answer that involves less typing than the accepted answer (and for my own reference when I forget this answer again next week).
This might be close to what you want:
git log --simplify-by-decoration --decorate --pretty=oneline "$committish" | fgrep 'tag: '
But, the more common situation is to just find the most recent tag:
git describe --tags --abbrev=0 "$committish"
--tags
will search against lightweight tags, do not use it if you only want to consider annotated tags.- Do not use
--abbrev=0
if you want to also see the usual “number of ‘commits on top’ and abbreviated hash” suffix (e.g. v1.7.0-17-g7e5eb8).
to list all tags reachable on the current branch:
git log --decorate=full --simplify-by-decoration --pretty=oneline HEAD | \
sed -r -e 's#^[^\(]*\(([^\)]*)\).*$#\1#' \
-e 's#,#\n#g' | \
grep 'tag:' | \
sed -r -e 's#[[:space:]]*tag:[[:space:]]*##'
I do not have enough reputation to comment on other people's posts, but this is in response to the answer and its comments at https://stackoverflow.com/a/7698213/2598329. In order to show all of the tags reachable by the current branch, including the tag on the HEAD commit, you can use the following:
git log --decorate --oneline | egrep '^[0-9a-f]+ \((HEAD, )?tag: ' | ssed -r 's/^.+tag: ([^ ]+)[,\)].+$/\1/g'
One caveat - I use super sed, so you may need to change my "ssed" to sed.
And for the hell of it, here it is in PowerShell:
git log --decorate --oneline | % { if ($_ -match "^[0-9a-f]+ \((HEAD, )?tag: ") { echo $_} } | % { $_ -replace "^.+tag: ([^ ]+)[,\)].+$", "`$1" }
-- -a
Windows-specific answer for anyone looking.
(Powershell has recently gone open-source & cross-platform so command given below will run on the systems other than Windows too.)
NOTE: below is for old versions of git or for specific use cases!
For powershell:
git log --simplify-by-decoration --decorate --pretty=oneline "$committish" | Select-String 'tag: '
you can also use: -CaseSensitive
flag for Select-String to make it case sensitive
For cmd:
git log --simplify-by-decoration --decorate --pretty=oneline | findstr -i "tag: "
you can remove -i
to make the search case sensitive
NOTE: For newer versions & cross-platform, cross-terminal as long as it supports git command:
git tag --merged <branchname>
you can use options like format, color, sort & many others with this. Check it all out here: https://git-scm.com/docs/git-tag
You could use this:
# get tags on the last 100 commits:
base_rev=master~100
end_rev=master
for rev in $(git rev-list $base_rev..$end_rev)
do
git describe --exact-match $rev 2> /dev/null
done
Here's how I list annotated tags matching a pattern (TAG_PREFIX*) in reverse chronological order. This recipe uses git-describe.
#!/usr/bin/env bash
tag=$(git describe --abbrev=0 --match TAG_PREFIX*)
until [ -z $tag ]; do
echo $tag
tag=$(git describe --abbrev=0 --match TAG_PREFIX* $tag^ 2>/dev/null);
done
This won't work if multiple tags matching the pattern point to the same commit. For that, here is another recipe that uses git-rev-list and git-tag to list all tags, matching TAG_PREFIX*, starting from a commit (HEAD in this example).
#!/usr/bin/env bash
git rev-list HEAD | while read sha1; do
tags=( "$(git tag -l --points-at $sha1 TAG_PREFIX*)" )
[[ ! -z ${tags[*]} ]] && echo "${tags[@]}" | sort -r
done
all answer only list tags, but if you want them in chronological order, you need to add --sort=taggerdate
or example:
git tag --merged release/11.x --sort=taggerdate
studio-1.4
llvmorg-10-init
llvmorg-11-init
llvmorg-11.0.0-rc1
llvmorg-11.0.0-rc2
llvmorg-11.0.0-rc3
llvmorg-11.0.0-rc4
llvmorg-11.0.0-rc5
llvmorg-11.0.0-rc6
llvmorg-11.0.0
There is a git branch --contains
(Git since 1.5.7, at least)
Efficient for large numbers of tags and gets easy format flexibility:
{ git rev-list --first-parent ${1:-HEAD}
git for-each-ref --format='%(objectname) %(objecttype) %(refname)
%(*objectname) *(%(objecttype)) %(refname)'
} \
| awk '
NF==1 { revs[$1]=1; next }
{ if ( $1 in revs ) print $1,$2,$3 }
'
which gets all refs, add refs/tags
to the f-e-r to restrict it.
git describe (or some variant of it) might be what you're looking for.
精彩评论