如何从(未签出的)远程存储库中获取最后一个标签?
在我的本地副本中,我使用describe
命令。
git describe --abbrev=0 --tags
但是我无法在远程存储中使用describe
如何从(未签出的)远程存储库中获取最后一个标签?
在我的本地副本中,我使用describe
命令。
git describe --abbrev=0 --tags
但是我无法在远程存储中使用describe
使用git ls-remote
命令可以获取远程存储库的引用列表。
要查看最新版本,请查看输出的最后一行:
git -c 'versionsort.suffix=-' ls-remote --tags --sort='v:refname' <repository>
如果要仅输出使用语义化版本的存储库中的最新标签(例如在shell脚本中),请使用:
git -c 'versionsort.suffix=-' \
ls-remote --exit-code --refs --sort='version:refname' --tags <repository> '*.*.*' \
| tail --lines=1 \
| cut --delimiter='/' --fields=3
对于没有--sort
标志的旧版Git(v2.18之前),或者不支持versionsort.suffix
(v2.4之前)的版本,请使用以下命令:git ls-remote --refs --tags <repository> \
| cut --delimiter='/' --fields=3 \
| tr '-' '~' \
| sort --version-sort \
| tail --lines=1
sort
的旧版本不具备 --version-sort
标记,因此本问题不在讨论范围内...
使用 --tags
确保列表仅包含标签引用。
这将包括已引用和取消引用的标签。这意味着某些标签将在 refname 末尾带有 ^{}
。(有关详细信息,请参见 StackOverflow 上的此问题)。
对于人类来说,这并不重要,但如果不想看到这些 ^{}
,请添加 --refs
。
可以使用 --sort
对引用列表进行排序。
排序选项使用 git for-each-ref
相同的排序键。由于我们没有所有本地信息,因此并非所有选项都可用(例如与日期有关的排序键)。
我们想要基于 引用名称 使用 版本排序。为此,我们使用 version:refname
键。这也可以缩写为 v:refname
。
这将按升序排序版本,这意味着最新版本将是 最后一个。
要反转列表,请在排序键前加上 -
:--sort='-v:refname'
。
此时,版本排序 将把发行候选版(例如 v2.28.0-rc2
)放在它们应该排在前面的稳定版本之后。
自 v2.12 以来,我们可以使用配置标记告诉 Git 对具有特定字符后缀的 refnames 进行排序,在没有该字符后缀的引用之后: git -c 'versionsort.suffix=-'
。
要始终像这样使用 versionsort.suffix
,可以全局设置:
git config --global 'versionsort.suffix' '-'
在版本 2.4 和版本 2.12 之间,该标志被称为 versionsort.prereleaseSuffix
。
在旧版 Git 中进行排序有一个技巧:连字符 -
在空格
前排序,但波浪号 ~
在空格后排序。因此,通过将破折号 -
替换为波浪号 ~
,可以按正确的顺序排序。可以使用 tr '-' '~'
进行操作。
由于我们只关心除最后一行以外的所有输出内容,因此只需显示尾部:tail --lines=1
。当然,如果列表按降序检索(使用 --sort='-v:refname'
),则为:head --lines=1
。
ls-remote 命令的输出还会输出引用哈希。ada126bd28d66c8c8ff5966a52d63ce2c9e4d031 refs/tags/v2.28.0-rc0
要仅显示实际的标签(即引用名称),可以截掉行的第一部分:cut --delimiter='/' --fields=3
最后需要注意的是,ls-remote可以使用筛选模式来仅显示与筛选模式匹配的引用。例如,对于语义化版本控制,我们可以使用:'*.*.*'
。不符合该模式的任何内容都将不会被显示。
如果存储库始终使用v
前缀的版本标签,则可以进一步缩小范围,如此'v*.*.*'
。
另一个例子是仅检索特定主版本的最新标签。例如,要仅查看存储库的版本2的标签,可以使用'v2.*'
。
请确保在筛选器周围使用引号,否则星号*
会给您带来麻烦!
使用筛选器时,最好使用--exit-code
标志。
这是因为Git将始终退出状态码0
以表示已成功与远程存储库通信。
对于人类消费者来说,这没问题,因为您会在屏幕上看到是否找到了任何引用。
但是,如果在shell脚本中使用此代码,则可能会有问题。
当在远程存储库中找不到匹配的引用时,可以告诉Git使用状态码2
。这是通过使用--exit-code
标志完成的。
这样脚本将知道什么时候出错!
显然,如果未使用筛选器,则使用--exit-code
没有太多意义。
假设我们想知道Git的最新标签是什么。
我们将执行:
git ls-remote --sort='version:refname' --tags https://github.com/git/git.git
这会返回一个长列表,其中包含所有标签的顺序,如下所示(为了保持清晰,已截断)。
...
4c8bcdda4d6e4757caf876ddc401b5392e874e21 refs/tags/v2.28.0
ada126bd28d66c8c8ff5966a52d63ce2c9e4d031 refs/tags/v2.28.0-rc0
bd42bbe1a46c0fe486fc33e82969275e27e4dc19 refs/tags/v2.28.0-rc0^{}
49bfe36405d1631a303992cac5cc408980a0454e refs/tags/v2.28.0-rc1
3ddac3d691c3633cd4d9a74c07e3b2301f546f77 refs/tags/v2.28.0-rc1^{}
84a0d5cc2107b83a791aa4034cc54874e1d50668 refs/tags/v2.28.0-rc2
b066807397fd55553f4910ede74839e319b661fd refs/tags/v2.28.0-rc2^{}
47ae905ffb98cc4d4fd90083da6bc8dab55d9ecc refs/tags/v2.28.0^{}
这告诉我们最新的标签是v2.28.0
。
另一个例子是全局设置versionsort.suffix
,然后只获取最后一个标签:
git config --global 'versionsort.suffix' '-'
git ls-remote --refs --sort=':refname' --tags https://github.com/git/git.git \
| tail --lines=1 | cut --delimiter='/' --fields=3
现在,让我们看看Git是否已经有了第3版!
$ git ls-remote --exit-code --refs --tags https://github.com/git/git.git 'v3.*'
$ echo $?
2 # nope, not yet
2.18
,git
已经有了一个内置的--sort
选项,专门用于对引用名称进行排序。git ls-remote --tags --sort="v:refname" git://github.com/git/git.git | tail -n1
^{}
),只需加入一些简单的 sed
。git ls-remote --tags --sort="v:refname" git://github.com/git/git.git | tail -n1 | sed 's/.*\///; s/\^{}//'
根据@Frederik Nord的建议,您还可以使用--refs
开关来摆脱^{}
,这样只留下一个sed
命令(使oneliner缩短4个字符):
git ls-remote --tags --refs --sort="v:refname" git://github.com/git/git.git | tail -n1 | sed 's/.*\///'
# output: v2.18.0
对于 git
版本在 2.18
之前的用户,以下是通过 sort
进行管道输出的组合:
git ls-remote --tags git://github.com/git/git.git | sort -t '/' -k 3 -V | awk -F/ '{ print $3 }' | awk '!/\^\{\}/' | tail -n 1
--refs
参数是否有助于删除一个 sed 命令,即去掉 {}? - Frederick Nord不幸的是,git ls-remote --tags
实际上按字母顺序列出标签(至少在1.7.2.5版本中是这样)。因此,在1.7.10、1.7.11或1.7.12成为最新标签的时候,1.7.9将会是列表中的最后一个标签:
git ls-remote --tags git://github.com/git/git.git |grep "1\.7\."
[...]
bf68fe0313c833fa62755176f6e24988ef7cf80f refs/tags/v1.7.9.6
cb2ed324fc917db0b79d7b1f3756575ffa5f70d5 refs/tags/v1.7.9.6^{}
3996bb24c84013ec9ce9fa0980ce61f9ef97be4d refs/tags/v1.7.9.7
d0f1ea6003d97e63110fa7d50bb07f546a909b6e refs/tags/v1.7.9.7^{}
然而,我们可以通过“sort”将这些结果导出以更接近我们寻找的结果:
git ls-remote --tags git://github.com/git/git.git |grep "1\.7\."| sort -g -k3 -t.
[...]
eab05abaeb51531e11835aaa4c26564a1babebac refs/tags/v1.7.9-rc2
eac2d83247ea0a265d923518c26873bb12c33778 refs/tags/v1.7.9-rc0^{}
f59f511e26b4924b22c6966e79fe4f754bc81dc6 refs/tags/v1.7.9.2
0e2d57fd50f61e668be3180bc8f25991ea88aa8c refs/tags/v1.7.10-rc1^{}
121f71f0da1bc9a4e1e96be2c3e683191a82a354 refs/tags/v1.7.10.4^{}
26e5c5d09334d157bd04f794f16f6e338d50c752 refs/tags/v1.7.10.3^{}
[...]
cffb45719f60d6fc2cc98ead6af88a895c63c9ac refs/tags/v1.7.12.4
d8cf053dacb4f78920c112d10c7be21e4f5a5817 refs/tags/v1.7.12.2^{}
dcd07fb6262fd8bb9f531890df3986a8b719a0b5 refs/tags/v1.7.12-rc0
e15c16de396a1e1f42001b03cb885ce64eb4098e refs/tags/v1.7.12-rc2^{}
虽然还不完全正确,但已经接近了。如果我们排除-rc和^{},并在最后的子版本号上添加一个额外的排序,那么对于大多数需求来说,可能已经足够接近了:
git ls-remote --tags git://github.com/git/git.git |grep "1\.7\."|grep -v -|grep -v {| sort -n -t. -k3 -k4
23ed9debf17263ed6bed478a4d6d86e71342c18a refs/tags/v1.7.11.6
527b331100ddba839cc54bb31c1bcd66acc08321 refs/tags/v1.7.11.7
14d20a75e3d57a872a8c81ae90dcc4c61ddba011 refs/tags/v1.7.12
51993a414a76120fda20d56ba767fa513d9ff440 refs/tags/v1.7.12.1
04043f4d1ae42bddee67d354a2e6fd2464592a1e refs/tags/v1.7.12.2
b38da673be332933b8f3a873ce46ffea08d2ee2c refs/tags/v1.7.12.3
cffb45719f60d6fc2cc98ead6af88a895c63c9ac refs/tags/v1.7.12.4
% git -c 'versionsort.suffix=-' ls-remote -t --exit-code --refs --sort=-v:refname \
https://github.com/robert7/nixnote2 'v*' \
| sed -En '1!q;s/^[[:xdigit:]]+[[:space:]]+refs\/tags\/(.+)/\1/gp'
v2.1.0-beta4g
在使用git ls-remote
命令时,通过添加--refs
参数可以消除其他答案中显示的{}
引用:
$ git ls-remote -t --refs <URL>
8f235769a2853c415f811b19cd5effc47cc89433 refs/tags/continuous
24e666ed73486a2ac65f09a1479e91e6ae4a1bbe refs/tags/continuous-develop
7c2cff2c26c1c2ad4b4023a975cd2365751ec97d refs/tags/v2.0
35b69eed46e5b163927c78497983355ff6a5dc6b refs/tags/v2.0-beta10
要仅获取标签名称,请执行以下操作:
sed -E 's/^[[:xdigit:]]+[[:space:]]+refs\/tags\/(.+)/\1/g'
:
$ git ls-remote -t --exit-code --refs https://github.com/robert7/nixnote2.git \
| sed -E 's/^[[:xdigit:]]+[[:space:]]+refs\/tags\/(.+)/\1/g'
continuous
continuous-develop
v2.0
v2.0-beta10
grep
和/或 head -n1
(或者如果您喜欢保持 PID 数字较低,可以添加到您的 sed
命令中)来传递经过清理的列表。v
开头,则添加 'v*'
。--exit-code
以确保在没有匹配的引用返回时退出非 0
。https://
版本:它更快,如果您正在打包,则不想冒被要求提供 ssh 密钥的风险。--sort=-v:refname
按版本而不是按词典顺序排序,并将最大版本放在顶部git -c versionsort.suffix=-
防止 2.0-rc
在 2.0
之后出现。git ls-remote --tags "#{github_repo}" | awk '{print $2}' | grep -v '{}' | awk -F"/" '{print $3}' | sort -n -t. -k1,1 -k2,2 -k3,3 | tail -n 1.chomp
这对我很有用 如何从Github远程仓库获取最新标签
这是我的一行代码 :-)
git ls-remote --tags --refs --sort="version:refname" git://github.com/git/git.git | awk -F/ 'END{print$NF}'
对于 Git < 2.0,不支持使用ls-remote --sort
命令:
用法:git ls-remote [--heads] [--tags] [-u | --upload-pack ] [-q|--quiet] [--exit-code] [--get-url] [ [...]]
要列出最新的标签,并包括旧版本的 Git,请使用内置的sort
命令。
按版本号(反向)的第二列排序打印标签:
git ls-remote --tags $my_repo | sort -Vr -k2
...哈希 ID... refs/tags/v0.10.0-rc0
...哈希 ID... refs/tags/v0.9.0-rc0
...哈希 ID... refs/tags/v0.9.0
...哈希 ID... refs/tags/v0.8.1
...哈希 ID... refs/tags/v0.8.0-rc1
使用 grep
获取特定版本的最新标签(例如,最新的 0.8 版本):
git ls-remote --tags $my_repo | sort -Vr -k2 | grep -Po -m 1 "tags/\K.*0.8.*"
v0.8.1
| awk -F/ '{ print $3 }'
- kilianc--sort="-version:refname"
。 - Nigel Thorne