简体   繁体   English

从远程仓库获取最后一个 git 标签,无需克隆

[英]Get last git tag from a remote repo without cloning

How to get last tag from a (non checked-out) remote repo?如何从(未签出的)远程仓库获取最后一个标签?

On my local copy I use describe在我的本地副本上,我使用describe

git describe --abbrev=0 --tags

But I cannot use describe with remote storage但我不能将describe与远程存储一起使用

TL;DR TL; 博士

With git ls-remote you can get a list of references from a remote repository.使用git ls-remote您可以从远程存储库中获取引用列表。

To see what the latest version is, look at the last line of output from:要查看最新版本,请查看以下输出的最后一行:

git -c 'versionsort.suffix=-' ls-remote --tags --sort='v:refname' <repository>

To only output the latest tag (for instance in a shell script) of a repository that uses Semantic Versioning use:输出使用语义版本控制的存储库的最新标记(例如在 shell 脚本中),请使用:

git -c 'versionsort.suffix=-' \
    ls-remote --exit-code --refs --sort='version:refname' --tags <repository> '*.*.*' \
    | tail --lines=1 \
    | cut --delimiter='/' --fields=3

For older versions of Git that don't have the --sort flag (pre v2.18), or versions that don't support versionsort.suffix (pre v2.4) use:对于没有--sort标志(v2.18 之前)的旧版本 Git,或不支持versionsort.suffix (v2.4 之前)的版本,请使用:

git ls-remote --refs --tags <repository> \
    | cut --delimiter='/' --fields=3     \
    | tr '-' '~'                         \
    | sort --version-sort                \
    | tail --lines=1

Older versions of sort that don't have the --version-sort flag are out of scope for this question...没有--version-sort标志的旧版本sort超出了这个问题的范围......


The long version长版

Tags only仅标签

Using --tags makes sure the list only contains tag references.使用--tags确保列表只包含标签引用。

This will include both referenced and de-referenced tags.这将包括引用和取消引用的标签。 That means some tags will have ^{} at the end of the refname.这意味着某些标签将在引用名称的末尾带有^{} (For more information about that see this question elsewhere on StackOverflow .) (有关更多信息,请参阅StackOverflow 上其他地方的这个问题。)

For human consumption this doesn't matter much, but if you don't want to see those ^{} 's add --refs .对于人类消费来说,这并不重要,但如果您不想看到那些^{}的添加--refs

Sorting排序

It is possible sort the list of references using --sort .可以使用--sort对引用列表进行排序。

The sort option uses the same sort keys as git for-each-ref . sort 选项使用与git for-each-ref相同的排序键。 As we don't have all of the information locally, not all of the options are available to us (for instance date related sort keys).由于我们在本地没有所有信息,因此并非所有选项都可供我们使用(例如与日期相关的排序键)。

We want to use version sort , based on the reference name .我们想使用基于引用名称的版本排序 To do so, we use the version:refname key.为此,我们使用version:refname键。 This can also be abbreviated to v:refname .这也可以缩写为v:refname

This will sort the versions ascending, meaning the latest version will be last .这将对版本进行升序排序,这意味着最新版本将是last

To reverse the list prepend the sort key with - : --sort='-v:refname' .要反转列表,请在排序键前加上- : --sort='-v:refname'

Pre-release sorting预发布排序

At this point, version-sort will place release candidates (for instance v2.28.0-rc2 ) after the stable version that they should come in front of.此时,版本排序会将候选版本(例如v2.28.0-rc2 )放在它们应该放在前面的稳定版本之后

Since v2.12 we can use a configuration flag that tells Git to sort refnames with a specific character suffix after references without that character suffix: git -c 'versionsort.suffix=-' .从 v2.12 开始,我们可以使用一个配置标志,告诉 Git没有该字符后缀的引用之后使用特定字符后缀对引用名进行排序: git -c 'versionsort.suffix=-'

To always use versionsort.suffix like this, it can be set globally:要始终像这样使用versionsort.suffix ,可以全局设置它:

git config --global 'versionsort.suffix' '-'

Between v2.4 and v2.12 the flag is called versionsort.prereleaseSuffix .在 v2.4 和 v2.12 之间,该标志称为versionsort.prereleaseSuffix

Sorting in older versions of Git在旧版本的 Git 中排序

For older Git versions a trick can be used: a dash character - is sorted before a space对于较旧的 Git 版本,可以使用一个技巧:破折号字符-空格之前排序 but a tilde ~ is sorted after a space.但是波浪号~一个空格之后排序。

So by replacing the dash - with a tilde ~ , things get sorted in the right order.因此,通过将破折号-替换为波浪号~ ,事情就会按正确的顺序排序。 This can be done using tr '-' '~'这可以使用tr '-' '~'来完成

One line only仅一行

As we don't really care for all of the output, other than the last line, we only show the tail: tail --lines=1 .由于我们并不真正关心所有输出,除了最后一行,我们只显示尾部: tail --lines=1 Of course, if the list is retrieved in descending order (with --sort='-v:refname' ), this would be: head --lines=1 .当然,如果按降序检索列表(使用--sort='-v:refname' ),这将是: head --lines=1

Just the Refname只是参考名称

The output from the ls-remote command also outputs the reference hash : ls-remote 命令的输出还输出参考哈希

ada126bd28d66c8c8ff5966a52d63ce2c9e4d031        refs/tags/v2.28.0-rc0

To only see the actual tag (ie the reference name), we can cut of the first part of the line: cut --delimiter='/' --fields=3为了只看到实际的标签(即引用名称),我们可以剪切该行的第一部分: cut --delimiter='/' --fields=3

Reference filter参考过滤器

The last thing to note is that ls-remote can be given a filter to only show reference that match the filter pattern.最后要注意的是,可以给 ls-remote 一个过滤器以显示与过滤器模式匹配的引用。 For instance, for Semantic Versioning we could use: '*.*.*' .例如,对于语义版本控制,我们可以使用: '*.*.*' Anything that does not match that pattern will not be shown.任何与该模式不匹配的内容都不会显示。

If the repository always prefixes a version tag with a v , it could be narrowed down further to 'v*.*.*' .如果存储库总是在版本标签前面加上v ,它可以进一步缩小到'v*.*.*'

Another example is to only retrieve the latest tag for a specific main version.另一个示例是仅检索特定主版本的最新标记。 For instance, to only see tags for verion 2 of a repo, we could use 'v2.*' .例如,要仅查看 repo 版本 2 的标签,我们可以使用'v2.*'

Make sure to use quotes around the filter, otherwise that star * will cause you trouble!确保在过滤器周围使用引号,否则星号*会给您带来麻烦!

Reference not found未找到参考

When using a filter it is a good idea to use the --exit-code flag.使用过滤器时,最好使用--exit-code标志。

This is because Git will always exit with status code 0 to indicate it successfully talked with the remote repository.这是因为 Git 将始终以状态代码0退出,以表明它已成功与远程存储库通信。

For human consumption this is fine, as you'll see on the screen if any refs have been found.对于人类消费,这很好,如果找到任何参考,您将在屏幕上看到。

If this code is used in a shell script, however, that can be problematic.但是,如果在 shell 脚本中使用此代码,则可能会出现问题。

Git can be told to use status code 2 when no matching refs are found in the remote repository.当在远程存储库中找不到匹配的引用时,可以告诉 Git 使用状态代码2 This is done by using the --exit-code flag.这是通过使用--exit-code标志来完成的。

That way a script will know when something goes wrong!这样脚本就会知道什么时候出错了!

Obviosuly, if no filter is used, using --exit-code does not really make sense.显然,如果不使用过滤器,使用--exit-code并没有真正意义。

Time for an example!是时候举个例子了!

Lets say we wanted to know what the latest tag of Git is.假设我们想知道 Git 的最新标签是什么。

We would do:我们会这样做:

git ls-remote --sort='version:refname' --tags https://github.com/git/git.git

That would return a long list with all the tags in order, as shown below (truncated for sanity's sake).这将返回一个按顺序排列所有标签的长列表,如下所示(为了理智而被截断)。

    ...

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^{}

This tells us the latest tag is v2.28.0 .这告诉我们最新的标签是v2.28.0

Another example would be to set versionsort.suffix globally and then get just the last tag:另一个例子是全局设置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

Now, let's see if there is already a version 3 of Git!现在,让我们看看是否已经有 Git 的第 3 版!

$ git ls-remote --exit-code --refs --tags https://github.com/git/git.git 'v3.*'
$ echo $?
2 # nope, not yet

Since version 2.18 git has a built-in --sort option for the exact purpose of sorting ref names.2.18版本开始, git 一个内置的--sort选项,用于对引用名称进行排序。

So the up-to-date command would be所以最新的命令是

git ls-remote --tags --sort="v:refname" git://github.com/git/git.git | tail -n1

To also remove the hash and the dereference marker ( ^{} ), just throw in some simple sed要同时删除散列和取消引用标记( ^{} ),只需放入一些简单的sed

git ls-remote --tags --sort="v:refname" git://github.com/git/git.git | tail -n1 | sed 's/.*\///; s/\^{}//'

As per suggestion by @Frederik Nord, you can also use the --refs switch to get rid of the ^{} , which leaves just one sed command (making the oneliner 4 characters shorter):根据@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

For git versions prior to 2.18 here's a combo for piping output through sort对于2.18之前的git版本,这里有一个通过sort管道输出的组合

git ls-remote --tags git://github.com/git/git.git | sort -t '/' -k 3 -V | awk -F/ '{ print $3 }' | awk '!/\^\{\}/' | tail -n 1

Unfortuntely, git ls-remote --tags actually lists tags alphabetically (at least as of 1.7.2.5).不幸的是, git ls-remote --tags实际上按字母顺序列出标签(至少从 1.7.2.5 开始)。 So, at the time that 1.7.10, 1.7.11 or 1.7.12 were the latest tags, 1.7.9 would have been the last on the list:因此,在 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^{}

However, we can pipe these results through 'sort' to get closer to the results we're looking for:但是,我们可以通过“排序”来传递这些结果,以更接近我们正在寻找的结果:

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^{}

While still not correct, it's closer.虽然仍然不正确,但已经接近了。 If we exclude -rc and ^{}, and add an additional sort on the last sub-version number, we can probably get close enough for most needs:如果我们排除 -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 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 远程存储库获取最新标签

TL;DR:特尔;博士:

% 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

Explanation解释

Pass --refs to git ls-remote to get rid of the {} refs shown in other answers:--refs传递给git ls-remote以摆脱其他答案中显示的{} refs:

$ git ls-remote -t --refs <URL>

This gives output such as:这给出了如下输出:

8f235769a2853c415f811b19cd5effc47cc89433        refs/tags/continuous
24e666ed73486a2ac65f09a1479e91e6ae4a1bbe        refs/tags/continuous-develop
7c2cff2c26c1c2ad4b4023a975cd2365751ec97d        refs/tags/v2.0
35b69eed46e5b163927c78497983355ff6a5dc6b        refs/tags/v2.0-beta10

To get only the tag names, pass through:要仅获取标签名称,请通过:

sed -E 's/^[[:xdigit:]]+[[:space:]]+refs\\/tags\\/(.+)/\\1/g' : 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

You can then pass the cleaned up list through an appropriate grep and/or head -n1 (or add to your sed command if you like keeping your PID numbers low.)然后,您可以通过适当的grep和/或head -n1传递清理后的列表(如果您希望保持较低的 PID 数字,则可以添加到您的sed命令中。)

Suggestions:建议:

  • Add a pattern at the end of the command line to filter.在命令行末尾添加模式以进行过滤。 Eg 'v*' if all version tags start with a v .例如'v*'如果所有版本标签都以v开头。
  • Pass --exit-code to ensure a non- 0 exit when no matching refs are returned.传递--exit-code以确保在没有返回匹配的引用时非0退出。
  • Use the https:// version: it's faster and if you're packaging you don't want to run the risk of being asked for a ssh key.使用https://版本:它更快,如果您正在打包,您不想冒被要求提供 ssh 密钥的风险。
  • --sort=-v:refname to sort by version rather than lexographically, and have the largest versions at the top --sort=-v:refname按版本而不是按字典顺序排序,并在顶部有最大的版本
  • Use git -c versionsort.suffix=- to prevent 2.0-rc coming "after" 2.0使用git -c versionsort.suffix=-防止2.0-rc出现在2.0

这是我的单线 :-)

git ls-remote --tags --refs --sort="version:refname" git://github.com/git/git.git | awk -F/ 'END{print$NF}'

For Git < 2.0 ls-remote --sort is not supported:对于Git < 2.0 ls-remote --sort不受支持:

usage: git ls-remote [--heads] [--tags] [-u |用法:git ls-remote [--heads] [--tags] [-u | --upload-pack ] [-q|--quiet] [--exit-code] [--get-url] [ [...]] --upload-pack ] [-q|--quiet] [--exit-code] [--get-url] [ [...]]

To list latest tags, with older Git releases as well, use the built-in sort command.要列出最新的标签以及较旧的 Git 版本,请使用内置的sort命令。

Printing tags, sorted by by version numbers (reversed) of the second column:打印标签,按第二列的版本号(倒序)排序:

git ls-remote --tags $my_repo | sort -Vr -k2

...hash id... refs/tags/v0.10.0-rc0 ...哈希ID ... refs/tags/v0.10.0-rc0
...hash id... refs/tags/v0.9.0-rc0 ...哈希ID ... refs/tags/v0.9.0-rc0
...hash id... refs/tags/v0.9.0 ...哈希ID ... refs/tags/v0.9.0
...hash id... refs/tags/v0.8.1 ...哈希ID ... refs/tags/v0.8.1
...hash id... refs/tags/v0.8.0-rc1 ...哈希ID ... refs/tags/v0.8.0-rc1

Use grep to get the latest tag of a specific version (for example, latest 0.8 version):使用grep获取特定版本的最新标签(例如最新的 0.8 版本):

git ls-remote --tags $my_repo | sort -Vr -k2 | grep -Po -m 1 "tags/\K.*0.8.*"

v0.8.1 v0.8.1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从远程仓库获取最后提交日期而不进行克隆 - Getting the last commit date from a remote repo without cloning "无需克隆即可从远程仓库获取最后的提交哈希" - Getting the last commit hash from a remote repo without cloning 在不克隆的情况下标记远程 git 回购 - Tagging a remote git repo without cloning it github 远程标签推送,无需克隆 repo - github remote tag push without cloning repo &#39;git tag - 包含 <commit> &#39;没有克隆回购? - 'git tag --contains <commit>' without cloning the repo? 标记远程git存储库而不克隆它 - Tag a remote git repository without cloning it 将文件从 web 应用程序(弹簧启动)提交到 git 远程存储库,而不首先将存储库克隆为本地? 这可能吗 - commit file from a web application (spring boot) into git remote repository without first cloning the repo as local? is this possible Mobaxterm Git克隆/推送终止,无需克隆或更新远程回购 - Mobaxterm Git clone/push terminates without cloning or updating remote repo 从远程 git 存储库克隆时权限被拒绝(公钥) - permission denied (publickey) when cloning from remote git repo 在远程 GIT 存储库上推送/创建新目录而不克隆整个存储库,只需使用 git init 初始化 - Pushing/creating new directory on remote GIT repo without cloning whole repo, just initialized with git init
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM