如何在 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.0ac1.0.5 命名的标签。其他名为1.0.01.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-listdescribe 的组合(***.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.1v0.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=&lt;pattern&gt;。例如获取最新版本标签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 开始的 seds 在 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。对于标签,authordatecommitterdate 是空的(所以作为排序键没用)。 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学习-本地标签管理

如何使用 git log --graph 显示标签名称和分支名称

Git使用详解Egit的常用操作详解

如何在 git 中获取最后一个合并的分支名称

如何在我的 PowerShell 提示符中显示我当前的 git 分支名称?

git进阶(分支与标签管理)