如何按照 rc-X.Y.Z.W 格式的版本字符串顺序对 git 标记进行排序?

当我输入命令时:

git tag -l

我得到了这样的结果:

rc-0.9.0.0
rc-0.9.0.1
rc-0.9.0.10
rc-0.9.0.11
rc-0.9.0.12
rc-0.9.0.2
rc-0.9.0.3
rc-0.9.0.4
rc-0.9.0.5
rc-0.9.0.6
rc-0.9.0.7
rc-0.9.0.8
rc-0.9.0.9

我想要的不是这个:

rc-0.9.0.0
rc-0.9.0.1
rc-0.9.0.2
rc-0.9.0.3
rc-0.9.0.4
rc-0.9.0.5
rc-0.9.0.6
rc-0.9.0.7
rc-0.9.0.8
rc-0.9.0.9
rc-0.9.0.10
rc-0.9.0.11
rc-0.9.0.12

如何对当前列表进行排序以得到这样的结果?

54211 次浏览

使用版本排序

git tag -l | sort -V

或者对于 git 版本 > = 2.0

git tag -l --sort=v:refname
git tag -l --sort=-v:refname # reverse

这个 perl 脚本(对看起来像 client_release/7.2/7.2.25的标记进行排序)适应您的特定标记方案。

使用 Git 2.0(2014年6月) ,您将能够指定排序顺序!

参见 犯下 b6de0c6,来自 提交9ef176b,由 易懂的泰语(pclouds)作者:

 --sort=<type>

按特定顺序排序。
支持的类型是:

  • refname”(字典顺序) ,
  • version:refname”或“ v:refname”(标签名称被视为版本)。

在“ -”前面加上反向排序顺序。


所以,如果你有:

git tag foo1.3 &&
git tag foo1.6 &&
git tag foo1.10

你会得到这样的结果:

# lexical sort
git tag -l --sort=refname "foo*"
foo1.10
foo1.3
foo1.6


# version sort
git tag -l --sort=version:refname "foo*"
foo1.3
foo1.6
foo1.10


# reverse version sort
git tag -l --sort=-version:refname "foo*"
foo1.10
foo1.6
foo1.3


# reverse lexical sort
git tag -l --sort=-refname "foo*"
foo1.6
foo1.3
foo1.10

提交 b150794(由 Jacob Keller 撰写,git 2.1.0,2014年8月)开始,您可以指定默认顺序:

tag.sort

这个变量控制由 git-tag显示的标记的排序。
如果没有提供“ --sort=<value>”选项,此变量的值将被用作默认值。

罗宾斯特 评论:

现在可以将版本排序顺序(Git 2.1 +)配置为默认值:

git config --global tag.sort version:refname

正如 Leo Galleguillos评论中指出的:

要将 Git 配置为显示 先看最新的牌子(正在下降顺序) ,只需添加一个 版本前加连字符
命令变成:

git config --global tag.sort -version:refname

Git 2.4(2015年第2季)ABC0配置变量可以用来指定 ABC1在 v1.0之前

参见 提交 f57610a by 滨野俊男(gitster)

注意(见下文) versionsort.prereleaseSuffix现在(2017)是 versionsort.suffix的一个不推荐的别名。


Git 2.7.1(2016年2月)将改善 git tag本身的输出。

提交0571979(2016年1月26日)及 提交1d094db(2016年1月24日) by 杰夫 · 金(peff)
(朱尼奥 · C · 哈马诺 gitster于2016年2月1日合并于 犯罪)

不要显示含糊不清的标签名称为“ tags/foo

B7cc53e(tag.c: use‘ ref-filter’API,2015-07-11)以来,git tag已经开始将名称不明确的标签(即同时存在“ heads/foo”和“ tags/foo”)显示为“ tags/foo”,而不仅仅是“ foo”。
这两者都是:

  • 没有意义; “ git tag”的输出只包括 refs/tags,所以我们知道“ foo”指的是“ refs/tags”中的那个。
  • 在原始输出中,我们知道行“ foo”意味着“ refs/tags/foo”存在。在新的输出中,我们不清楚我们指的是“ refs/tags/foo”还是“ refs/tags/tags/foo”。

发生这种情况的原因是,提交 b7cc53e 将 git tag切换为使用 ref-filter 的“ %(refname:short)”输出格式,该格式是从 for-each-ref改编而来的。这个更一般的代码不知道我们只关心标记,而是使用 shorten_unambiguous_ref来获取 short-name
我们需要告诉它,我们只关心“ refs/tags/”,它应该相对于该值缩短。

让我们为格式化语言“ strip”添加一个新的修饰符,以删除一组特定的前缀组件。
这修复了“ git tag”,并允许用户从他们自己的定制格式(“ tag”或“ for-each-ref”)中调用相同的行为,同时在所有位置保留“ :short”的相同含义。

如果附加了 strip=<N>,那么从 refname 前面剥离 <N>斜杠分隔的路径组件(例如,%(refname:strip=2)refs/tags/foo转换为 foo)。
<N>必须是正整数。
如果显示的参考文献的组件少于 <N>,则命令中止,并出现错误。

对于 git tag,如果未指定,则默认为 %(refname:strip=2)


更新 Git 2.12(2017年第1季)

提交编号 C026557提交 b178464提交51acfa9提交 b823166提交109064a提交0c1b487承认9ffda48提交 eba286e(2016年12月8日) by 赛德尔加博尔(szeder)
(由 朱尼奥 · C · 哈马诺 gitster于2017年1月23日在 犯下1ac244d合并)

versionsort.prereleaseSuffixversionsort.suffix的别名。

中使用的版本比较的 prereleaseSuffix特性 “ git tag -l”没有正确时,两个或更多的预发行为 同样的释放存在(例如当 2.02.0-beta12.0-beta2 代码需要比较 2.0-beta12.0-beta2)。

最后,我编写了一个简单的 shell 脚本来简化这个任务。

#!/usr/bin/env bash


TAGS=$(git tag)
CODE=$?


if [ $CODE = 0 ]; then
echo "$TAGS" | sort -V
fi


exit $CODE

我将其保存为 git-tags,并在需要列出标记时运行 git tags

根据这个 回答,在像 Windows 和 OSX 这样不支持 sort -V的平台上,你可以使用

git tag -l | sort -n -t. -k1,1 -k2,2 -k3,3 -k4,4

使用 sort -V方法进行反向排序:

git tag -l | sort -V --reverse

综合这里已有的答案:

本地存储库

git -c 'versionsort.suffix=-' tag --list --sort=-v:refname
  • suffix=-将防止 2.0-rc来“之后”2.0
  • --sort=-将把最高的版本号放在顶部。

远程存储库

git -c 'versionsort.suffix=-' ls-remote -t --exit-code --refs --sort=-v:refname "$repo_url" \
| sed -E 's/^[[:xdigit:]]+[[:space:]]+refs\/tags\/(.+)/\1/g'

这样做的好处是不会从远程下载任何对象。

更多信息见 这个答案

如果您在 Linux 上并且使用 ZSH ,那么只需使用 gtl命令。

别名代码:
gtl='gtl(){ git tag --sort=-v:refname -n -l "${1}*" }; noglob gtl'

特殊格式的尝试列表与最后一个

git tag -l --sort=refname | grep -E '^\d+\.\d+\.\d+.*' | tail -n 1

或者第一次

git tag -l --sort=refname | grep -E '^\d+\.\d+\.\d+.*' | head -n 1