在Unix或GNU脚本环境中(例如Linux发行版,Cygwin,OSX),最佳方法是如何确定当前checkout是否为Git标签。如果是标签,如何确定标签名称?
其中一种使用此技术的方法是自动标记发布(例如像Subversion中的
请参阅我关于编程检测Git分支的相关问题。
其中一种使用此技术的方法是自动标记发布(例如像Subversion中的
svnversion
所做的操作)。请参阅我关于编程检测Git分支的相关问题。
git describe --exact-match HEAD
(这个命令将只考虑已注释的标签,但你应该使用已注释并且可能甚至是已签名的标签来标记发布。)
如果您想考虑所有标签,包括轻量级标签(通常用于本地标记),您可以使用--tags
选项:
git describe --exact-match --tags HEAD
但我认为你在这里遇到了"XY问题",因为你问的是关于可能解决问题的方法,而不是询问问题本身...它可以有更好的解决方案。
解决你的问题的方法是看一下Git在GIT-VERSION-GEN脚本中如何实现,并查看它如何在Makefile中使用。
git describe --exact-match HEAD
和 git describe --exact-match --tags HEAD
,如果您使用轻量级标签,则需要使用 --tags
选项。建议使用带有签名的标签(即标签对象)来标记发布版本。 - Jakub Narębski
git name-rev --name-only --tags HEAD
git_tag=`git name-rev --name-only --tags HEAD | sed 's/^undefined$//'`
$ git checkout master
Already on "master"
$ git name-rev --name-only --tags HEAD
undefined
$ git checkout some-tag
Note: moving to "some-tag" which isnt a local branch
If you want to create a new branch from this checkout, you may do so
(now or later) by using -b with the checkout command again. Example:
git checkout -b <new_branch_name>
HEAD is now at 1234567... Some comment blah blah
$ git name-rev --name-only --tags HEAD
some-tag
git-name-rev是脚本中首选的使用方式,因为它是git基础设施的一部分,而git-describe则是外壳的一部分。
如果HEAD指向标签,请使用此命令打印标签的名称,否则不打印任何内容。
git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null | sed -n 's/^\([^^~]\{1,\}\)\(\^0\)\{0,1\}$/\1/p'
注意将标准错误重定向到/dev/null,否则您将收到一个错误消息,内容为:
fatal: cannot describe 'SOMESHA'"
编辑:已修复sed中的正则表达式,支持轻量级标签和注释/签名标签。
git describe
命令:
git-describe - 显示可从提交访问的最近标签
该命令查找可从提交访问的最近标签。如果标签指向提交,则仅显示标签。否则,它会将标签名称后缀为附加提交数和最近提交的缩写对象名称。
git-describe --tags
? 但更重要的是,很难确定您是否处于正确的标签上。 您需要解析输出并查找连字符。但是,如果标签名称中有连字符怎么办?因此,出于这个原因,我更喜欢使用 git name-ref --name-only --tags HEAD
。 - JasonSmithgit describe
来自动标记发布版本。 - Greg Hewgill--exact-match
选项仅查找直接指向提交的标签。 - Jakub Narębski--exact-match
时,我喜欢你的解决方案。这样如果不是标签检出就会有一个错误代码。不幸的是,我可能不得不重定向stderr,但你不能赢得所有的胜利! - JasonSmithgit describe --exact-match(--tags)
给出了所有(带注释的)标记中的“第一个”。git describe
会将它们排序:
git_tag
变量设置为当前检出标签的名称,如果检出未被标记,则将其留空。git_tag=''
this_commit=`git log --pretty=format:%H%n HEAD^..`
for tag in `git tag -l`; do
tag_commit=`git log --pretty=format:%H%n tags/$tag^..tags/$tag`
if [ "$this_commit" = "$tag_commit" ]; then
# This is a tagged commit, so use the tag.
git_tag="$tag"
fi
done
Jakub Narębski的评论:
这个解决方案可以简化为循环遍历所有标签,并检查它们是否指向正确的提交,即HEAD所指向的对象。使用plumbing命令,也就是用于脚本编写的命令,可以将其编写为:
this_commit=$(git rev-parse --verify HEAD)
git for-each-ref --format="%(*objectname) %(refname:short)" refs/tags/ |
while read tagged_object tagname
do
if test "$this_commit" = "$tagged_object"
then
echo $tagname
fi
done
这将打印指向当前提交的所有标签。
git name-rev
的回答进行了反对,因为它可能会返回例如“some-tag〜5”的结果;以及对基于git log
和git tag -l
组合的回答进行了反对,因为它既难看又低效。 - Jakub Narębski