如何在 Git 的当前分支中获取最新的标签名称?
Posted
技术标签:
【中文标题】如何在 Git 的当前分支中获取最新的标签名称?【英文标题】:How can I get the latest tag name in current branch in Git? 【发布时间】:2010-11-27 03:34:27 【问题描述】:在 Git 中获取最新标签的最简单方法是什么?
git tag a HEAD
git tag b HEAD^^
git tag c HEAD^
git tag
输出:
a
b
c
我应该写一个脚本来获取每个标签的日期时间并比较它们吗?
【问题讨论】:
最新创建的标签还是按提交日期排序的最新标签?您接受的答案显示最新创建的标签。如果决定更改现有标签,这可能是一个问题... 【参考方案1】:describe
在 CI/CD 进程中的问题是您可能会遇到 fatal: no tags can describe
错误。
这会发生,因为,根据git describe --help
:
该命令查找可从提交访问的最新标记。
如果你想要repo中的最新标签,不管你所在的分支是否可以到达标签,通常是因为它不是当前分支树的一部分,这个命令会给你整个最近创建的标签回购:
git tag -l --sort=-creatordate | head -n 1
【讨论】:
【参考方案2】:git describe --abbrev=0 --tags
如果您没有看到最新标签,请确保在运行之前获取来源:
git remote update
【讨论】:
谢谢,只需按照其他答案中的建议执行git describe --abbrev=0
即可返回不是最新本地标签的 v1.0.0,添加 --tags
但会给出正确的标签。【参考方案3】:
我不确定为什么对问题的要求没有答案。即所有标签(包括未注释的)并且没有后缀:
git describe --tags --abbrev=0
【讨论】:
【参考方案4】:获取最新的标签(之后的示例输出):
git describe --tags --abbrev=0 # 0.1.0-dev
要获取最新的标记,以及标记对象顶部的附加提交次数等:
git describe --tags # 0.1.0-dev-93-g1416689
获取最新的注释标签:
git describe --abbrev=0
【讨论】:
是的,正如git describe
的手册页所说:--abbrev=<n> [...] An <n> of 0 will suppress long format, only showing the closest tag.
如果你有两个标签指向同一个提交,这个答案(可能还有其他答案)会遇到麻烦。除非标签是带注释的标签,否则我认为 git 没有办法区分这两者中的哪一个是之前创建的。
如果我有两个以上的标签,那么这不会全部打印出来
如果你想直接签出最近的标签:git checkout $(git describe --abbrev=0 --tags)
这个答案比当前的“接受”更好,因为它提供了确切的命令行来使用,而不仅仅是“查看文档”【参考方案5】:
git tag --sort=-refname | awk 'match($0, /^[0-9]+\.[0-9]+\.[0-9]+$/)' | head -n 1
这会在所有与语义版本控制匹配的分支中获取最新标签。
【讨论】:
但前提是它们正好有三个段,并且也不能正确处理排序...9.9.9
将在10.1.1
之后返回【参考方案6】:
这里没有太多提及未注释的标签和带注释的标签。 'describe' 适用于带注释的标签并忽略未注释的标签。
这很难看,但可以完成所要求的工作,并且不会在其他分支上找到任何标签(而不是在命令中指定的标签上:下面示例中的 master)
过滤应该被优化(合并),但同样,这似乎是工作。
git log --decorate --tags master |grep '^commit'|grep 'tag:.*)$'|awk 'print $NF'|sed 's/)$//'|head -n 1
欢迎批评,因为我现在要使用它:)
【讨论】:
【参考方案7】:git tag --sort=committerdate | tail -1
【讨论】:
请解释这段代码 sn-p 将如何解决问题,而不是发布仅代码的答案。 这将显示所有标签,而不仅仅是当前分支的标签。【参考方案8】:如果您需要在 当前分支 上获取 最新标签名称(按标签日期)的单行:
git for-each-ref refs/tags --sort=-taggerdate --format=%(refname:short) --count=1 --points-at=HEAD
我们使用它来设置设置中的版本号。
输出示例:
v1.0.0
也适用于 Windows。
【讨论】:
在 Linux (Debian Stretch) 上我得到-bash: syntax error near unexpected token '('
如果我将那部分用引号括起来(即--format="%(refname:short)"
)并跳过--points-at=HEAD
它可以工作。最后一个开关它什么也没返回,我猜是因为我的HEAD
没有被标记?
@JeremyDavis,是的,我认为那是因为您的 HEAD
没有被标记。【参考方案9】:
您可以执行:git describe --tags $(git rev-list --tags --max-count=1)
在这里谈过:How to get latest tag name?
【讨论】:
我从最高/接受的答案开始,然后一路向下。这是第一个真正给我最新标签的答案(不知道为什么,但普通的旧git describe ...
返回一个较早的标签?!)
这是唯一适合我的。尝试了一些--abbrev=0
答案,他们切断了我想要的部分标签。【参考方案10】:
如果你的标签是可排序的:
git tag --merged $YOUR_BRANCH_NAME | grep "prefix/" | sort | tail -n 1
【讨论】:
【参考方案11】:如果您想查找应用于特定分支的最后一个标签,您可以尝试以下操作:
git describe --tag $(git rev-parse --verify refs/remotes/origin/"branch_name")
【讨论】:
【参考方案12】:对于所提出的问题,
如何获取当前分支最新的标签名
你想要的
git log --first-parent --pretty=%d | grep -m1 tag:
--first-parent
告诉git log
不要详细说明任何合并的历史,--pretty=%d
说只显示装饰,即任何提交的本地名称。 grep -m1
说“只匹配一个”,所以你只会得到最新的标签。
【讨论】:
【参考方案13】:要仅在当前分支/以当前分支为前缀的标签名称上获取最新标签,我必须执行以下操作
BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags --abbrev=0 $BRANCH^ | grep $BRANCH
分公司主:
git checkout master
BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags
--abbrev=0 $BRANCH^ | grep $BRANCH
master-1448
分支自定义:
git checkout 9.4
BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags
--abbrev=0 $BRANCH^ | grep $BRANCH
9.4-6
我最后需要增加并获得标签 +1 以进行下一次标记。
BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags --abbrev=0 $BRANCH^ | grep $BRANCH | awk -F- 'print $NF'
【讨论】:
【参考方案14】:git tag -l ac* | tail -n1
获取带有前缀“ac”的最后一个标签。例如,以ac1.0.0
或ac1.0.5
命名的标签。其他名为1.0.0
、1.1.0
的标签将被忽略。
git tag -l [0-9].* | tail -n1
获取最后一个标签,其第一个字符是0-9
。因此,第一个字符为a-z
的标签将被忽略。
更多信息
git tag --help # Help for `git tag`
git tag -l <pattern>
列出名称与给定模式匹配的标签(如果不匹配则全部列出) 模式已给出)。不带参数运行“git tag”也会列出 所有标签。该模式是一个外壳通配符(即,匹配使用 fnmatch(3))。可以给出多种模式;如果其中任何一个 匹配,显示标签。
tail -n <number> # display the last part of a file
tail -n1 # Display the last item
更新
对于git tag --help
,关于sort
参数。如果tag.sort
属性不存在,它将默认使用lexicorgraphic order
。
排序顺序 默认为为 tag.sort 变量配置的值,如果它 存在,否则字典顺序。请参阅 git-config(1)。
经过google,someone saidgit 2.8.0 支持以下语法。
git tag --sort=committerdate
【讨论】:
它不适合我,最后一个标签是 2.11.174 但这个打印 2.11.99 因为排序不是版本控制【参考方案15】:这是一个旧线程,但似乎很多人都错过了对 OP 问题的最简单、最简单和最正确的答案:要获取 当前分支 的最新标签,请使用git describe HEAD
。完成。
编辑:您还可以提供任何有效的 refname,甚至是遥控器;即,git describe origin/master
将告诉您可以从 origin/master 访问的最新标签。
【讨论】:
没有任何东西可以保证“最新标签”被任何分支处理。两个可行的解决方案是for-each-ref
命令(***.com/a/5261470/515973)和rev-list
和describe
的组合(***.com/a/7979255/515973)
这没有为我获取最新的标签。
git describe branchname --tags
确实可以让我在分支上获取最新标签(git 版本 2.12.2)【参考方案16】:
所有建议的错误是什么(Matthew Brett 解释除外,此答案是最新的)?
当您在 不同的历史点 时,只需在 jQuery Git 历史记录上运行其他人提供的任何命令,并使用 visual tagging history representation 检查结果(我 did 这就是你看到这篇文章的原因):
$ git log --graph --all --decorate --oneline --simplify-by-decoration
今天许多项目在主线的单独分支中执行发布(以及标记)。
这有强有力的理由。只要看看任何完善的 JS/CSS 项目。对于用户约定,它们在 DVCS 中携带二进制/缩小版本文件。作为项目维护者,您自然不希望用无用的二进制 blob 将您的主线 diff 历史弄得一团糟,并在主线之外执行构建工件的提交。
因为 Git 使用 DAG 而不是线性历史 - 很难定义距离度量,所以我们可以说 - 哦,rev 最接近我的 HEAD
!
我开始了自己的旅程(看看里面,我没有将精美的证明图片复制到这篇长篇文章中):
What is nearest tag in the past with respect to branching in Git?
目前我对标签和修订之间的距离有4个合理的定义,随着有用性的降低:
最短路径长度从HEAD
到合并基数与标签
合并基数在HEAD
和标签之间的日期
转数可从 HEAD 访问但无法从标签访问
标记的日期,无论合并基数
我不知道如何计算最短路径的长度。
根据HEAD
和标签之间合并基数的日期对标签进行排序的脚本:
$ git tag \
| while read t; do \
b=`git merge-base HEAD $t`; \
echo `git log -n 1 $b --format=%ai` $t; \
done | sort
它可用于大多数项目。
根据转数对标签进行排序的脚本,可以从 HEAD 访问但不能从标签访问:
$ git tag \
| while read t; do echo `git rev-list --count $t..HEAD` $t; done \
| sort -n
如果您的项目历史在提交时有奇怪的日期(因为 rebase 或其他历史重写或某些白痴忘记更换 Bios 电池或您对历史执行的其他魔法),请使用上述脚本。
对于标签的最后一个选项(标签的日期,无论合并基数),以获取按日期排序的标签列表:
$ git log --tags --simplify-by-decoration --pretty="format:%ci %d" | sort -r
要知道当前的修订日期,请使用:
$ git log --max-count=1
请注意,git describe --tags
有其自身的用途,但不能用于查找项目历史中人类预期的最近标记。
注意您可以在任何修订版中使用上述配方,只需将 HEAD
替换为您想要的!
【讨论】:
【参考方案17】:将在所有分支中输出最新标记提交的标签
git describe --tags $(git rev-list --tags --max-count=1)
【讨论】:
或TAG=$(git describe --tags $(git rev-list --tags --max-count=1))
@william-pursell
这是最好的答案。它实际上在所有分支中获取标签,而不仅仅是当前分支,就像当前的“正确”答案一样。
@michaeltwofish,当时我不知道,后来我想通了,并相应地纠正了我的答案。对此感到抱歉。
注意:这个命令返回“最新”标签,即使这个标签在另一个分支上。
我不同意问题是关于特定分支的说法。问题的标题暗示了这一点,但实际提出的问题是“在 Git 中获取最新标签的最简单方法是什么?”如果标题是问题,我想这是一个元问题。【参考方案18】:
“最近”在 git 中可能有两种含义。
您的意思可能是“哪个标签的创建日期最晚”,这里的大部分答案都是针对该问题的。就您的问题而言,您需要返回标签c
。
或者您可能的意思是“哪个标签在开发历史中最接近某个命名分支”,通常是您所在的分支HEAD
。在您的问题中,这将返回标签a
。
当然,这些可能会有所不同:
A->B->C->D->E->F (HEAD)
\ \
\ X->Y->Z (v0.2)
P->Q (v0.1)
假设开发者在星期一将Z
标记为v0.2
,然后在星期二将Q
标记为v0.1
。 v0.1
是最近的,但v0.2
在开发历史上更接近 HEAD,因为它的路径始于更接近 HEAD 的点。
我认为您通常想要第二个答案,更接近开发历史。您可以通过对每个标签使用 git log v0.2..HEAD
等来找到它。这为您提供了 HEAD 上的提交次数,因为以 v0.2
结尾的路径与 HEAD 所遵循的路径不同。
这是一个 Python 脚本,它通过遍历所有运行此检查的标签,然后打印出 HEAD 上提交次数最少的标签,因为标签路径不同:
https://github.com/MacPython/terryfy/blob/master/git-closest-tag
git describe
做了一些稍微不同的事情,因为它从(例如)HEAD 回溯以找到从 HEAD 回到历史路径上的第一个标签。在 git 术语中,git describe
查找来自 HEAD 的“可访问”标签。因此,它不会找到像v0.2
这样不在从 HEAD 返回的路径上的标签,而是从那里分岔的路径。
【讨论】:
【参考方案19】:这个怎么样?
TAG=$(git describe $(git rev-list --tags --max-count=1))
从技术上讲,不一定会给你最新的标签,而是最新的被标记的提交,它可能是也可能不是你正在寻找的东西。
【讨论】:
这个没有得到当前分支的最新标签,而是任何分支。太好了,因为这正是我所需要的。谢谢温森特。 如果您需要获取标签匹配模式,您可以在rev-list
中使用--tags=<pattern>
。例如获取最新版本标签git describe --tags $(git rev-list --tags='v[0-9].[0-9]*' --max-count=1)
$(git describe --contains $(git rev-parse HEAD))
谢谢,它成功了,但是,我必须添加 --tags git describe --tags $(git rev-list --tags --max-count=1)
【参考方案20】:
git log --tags --no-walk --pretty="format:%d" | sed 2q | sed 's/[()]//g' | sed s/,[^,]*$// | sed 's ...... '
如果您需要最后一个以上标签
(git describe --tags 有时会给出错误的哈希值,我不知道为什么,但对我来说 --max-count 2 不起作用)
这就是您可以按时间倒序获取最新 2 个标签名称的列表的方法,在 git 1.8.4 上完美运行。 对于早期版本的 git(如 1.7.*),输出中没有“tag:”字符串 - 只需删除最后一个 sed 调用
如果您想要超过 2 个最新标签 - 将此“sed 2q”更改为“sed 5q”或您需要的任何内容
然后您可以轻松地将每个标签名称解析为变量左右。
【讨论】:
这真的很有帮助,如果部署中断,许多开发人员会尝试通过回滚到以前的标签来自动化发布过程。好东西!!! 更进一步:git log --tags --no-walk --pretty="format:%D" | sed -nr '5q;s;^.*(tag: )([^,]*).*;\2;p'
where in %D
不包括周围的 ()
字符,而从 5q 开始的 sed
s 在 5 之前留下 4 行,然后打印出 ' 之间的所有字符标签:`和第一个','。所以......假设标签内没有使用逗号,这很有效。【参考方案21】:
要获取最新的标签,您可以:
$ git for-each-ref refs/tags --sort=-taggerdate --format='%(refname)' --count=1当然,您可以根据需要更改计数参数或排序字段。它出现 你可能想问一个稍微不同的问题,但这确实回答了我解释的问题。
【讨论】:
这几乎正是我正在寻找的(所有分支中的最新标签),但至少在我的 git 版本(1.7.7.6)中,标签的生成顺序相同--sort=-authordate
和 --sort=authordate
.
啊哈,因为你真正想要的是--sort=-taggerdate
。对于标签,authordate
和 committerdate
是空的(所以作为排序键没用)。
git for-each-ref refs/tags --sort=-taggerdate --format='%(refname:short)' --count=1
更好:)
请注意,它根据标记时间返回“最新”标签,可能不是树中最近的“最新”标签。例如,您可以签出任何先前的提交并标记该提交。 “最新”标签将是新创建的标签。
--points-at=$SHA
会给你一个提交哈希的标签。【参考方案22】:
git describe --tags
返回当前分支可以看到的最后一个标签
【讨论】:
【参考方案23】:如果您需要最后两个标签(例如,为了在当前标签和前一个标签之间生成更改日志),以下内容适用于我。我仅在最新标签为HEAD
的情况下对其进行了测试。
PreviousAndCurrentGitTag=`git describe --tags \`git rev-list --tags --abbrev=0 --max-count=2\` --abbrev=0`
PreviousGitTag=`echo $PreviousAndCurrentGitTag | cut -f 2 -d ' '`
CurrentGitTag=`echo $PreviousAndCurrentGitTag | cut -f 1 -d ' '`
GitLog=`git log $PreviousGitTag..$CurrentGitTag --pretty=oneline | sed "s_.\41\\(.*\)_; \1_"`
它适合我的需要,但由于我不是 git 向导,我相信它可以进一步改进。我还怀疑如果提交历史向前移动,它会中断。我只是分享以防万一。
【讨论】:
【参考方案24】:我的第一个想法是您可以使用git rev-list HEAD
,它按时间倒序列出所有转速,并结合git tag --contains
。当您找到 git tag --contains
生成非空列表的 ref 时,您已找到最新的标签。
【讨论】:
【参考方案25】:您可以查看git describe
,它的功能与您的要求相近。
【讨论】:
使用--abbrev=0
它应该返回最接近的 annotated 标签
返回当前分支中最新的标签。
要获得最新的注释标签,它针对当前分支中的当前提交,使用git describe --exact-match --abbrev=0
.
这个带有 cmets 的答案没有为我提供正确的标签。 @kilianic 提供了正确的解决方案。
git describe --tags
并比较 com github 发布页面中的最后一个标签以上是关于如何在 Git 的当前分支中获取最新的标签名称?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 git log --graph 显示标签名称和分支名称