删除不再位于远程存储库中的本地git标记

kEN*_*END 432 git git-tag

我们在git中使用标签作为部署过程的一部分.有时,我们希望通过从远程存储库中删除它们来清理这些标记.

这非常简单.一个用户在一组命令中删除本地标签和远程标签.我们有一个结合了两个步骤的小shell脚本.

第二个(第3个,第4个......)用户现在拥有不再反映在遥控器上的本地标签.

我正在寻找一个类似于git remote prune origin清除本地跟踪已删除远程分支的分支的命令.

或者,可以使用列出远程标记的简单命令来比较通过返回的本地标记git tag -l.

小智 977

这是一个很好的问题,我一直想知道同样的事情.

我不想写一个脚本,所以寻求一个不同的解决方案.关键是发现你可以在本地删除标签,然后使用git fetch从远程服务器"取回".如果遥控器上不存在该标签,则它将保持删除状态.

因此,您需要按顺序键入两行:

git tag -l | xargs git tag -d
git fetch --tags
Run Code Online (Sandbox Code Playgroud)

这些:

  1. 删除本地仓库中的所有标签.FWIW,xargs将每个标记输出"tag -l"放在"tag -d"的命令行中.没有这个,git不会删除任何东西,因为它不会读取stdin(愚蠢的git).

  2. 从远程仓库获取所有活动标签.

这甚至适用于Windows.

  • 这一定是我在StackOverflow上最喜欢的git答案.它结合了知识,简单和诡计,解释了一切.大 (54认同)
  • 如单独的答案中所述,这将删除所有本地标记,而不会重新创建不在远程仓库中的标记 (25认同)
  • FWIW这应该是完全没必要的.应该有一个`git tag prune origin`命令. (10认同)
  • 这可能对每个人都不起作用.你应该做git fetch --tags以保证安全. (8认同)
  • 我不得不去`git tag -l | %{git tag -d $ _}`让这个在PowerShell中运行.不确定其他人. (5认同)
  • 第一个命令是否需要`xargs`扩展名?我在windows cmd中执行该命令时得到这个:`'xargs'不被识别为内部或外部命令,可操作程序或批处理文件. (2认同)
  • @Web_Designer:我假设你在这里使用Windows.您需要使用真正的git-bash或将git安装目录与路径中的xargs可执行文件一起使用. (2认同)
  • 对于 powershell,您还可以使用: git tag -l | ForEach-Object {git tag -d $_} (2认同)

log*_*yth 236

从Git v1.7.8到v1.8.5.6,您可以使用:

git fetch <remote> --prune --tags
Run Code Online (Sandbox Code Playgroud)

更新

由于提交e66ef7ae6f31f2,这不适用于较新版本的git(从v1.9.0开始).我真的不想删除它,因为它确实适用于某些人.

正如"Chad Juliano"所建议的那样,自v1.7.8以来的所有Git版本都可以使用以下命令:

git fetch --prune <remote> +refs/tags/*:refs/tags/*
Run Code Online (Sandbox Code Playgroud)

您可能需要用引号括起标记部分(例如在Windows上)以避免通配符扩展:

git fetch --prune <remote> "+refs/tags/*:refs/tags/*"
Run Code Online (Sandbox Code Playgroud)

  • 这在版本1.9.0上对我不起作用 (9认同)
  • @Alex那只是因为zsh扩展了`*`但如果你单引号说它应该没问题. (3认同)
  • @ v01pe - 现在有一个git快捷方式--prune-tags可用,因为在PRUNING部分的文档中描述了git 2.17.0:https://git-scm.com/docs/git-fetch/2.17.0来自document:--prune-tags选项相当于在远程的refspecs中声明了refs/tags/*:refs/tags/*.等价:`git fetch origin --prune --prune-tags`或`git fetch origin --prune'refs/tags/*:refs/tags/*'`OR`git fetch <url of origin> --prune - -prune-tags`或`git fetch <url of origin> --prune'refs/tags/*:refs/tags/*'` (3认同)
  • 至于记录,这至少从版本1.7.9.5开始 (2认同)
  • 我指的是用于Windows 1.9.4-preview20140611的Git打包的文档(我怀疑所有以前的版本).我使用"git fetch --help"访问所述文档[quote]如果仅仅因为默认标记自动跟踪或由于--tags选项而被提取,则标签不受修剪.[/ quote] (2认同)
  • `git fetch --prune <remote> + refs/tags/*:refs/tags/*`在ZSH中不起作用但它在BASH中有效 (2认同)
  • git fetch origin --prune --prune-tags`修剪远程跟踪分支和标签。在git 2.18版本中签入。 (2认同)

new*_*ngt 150

如果您只想要遥控器上存在的那些标签,请删除所有本地标签:

$ git tag -d $(git tag)
Run Code Online (Sandbox Code Playgroud)

然后获取所有远程标签:

$ git fetch --tags
Run Code Online (Sandbox Code Playgroud)

  • +1比"git tag -l | xargs git tag -d"更好 (14认同)
  • @ocroquette,我不确定它比`xargs`更好。如果您的标签数量超过“ ARG_MAX”或类似的限制,则此方法将无效。不太可能,但是有可能,这就是xargs很棒的原因。 (3认同)
  • “好”是一个主观的东西,每个人都会发表自己的看法。关于ARG_MAX,是的。但是,在我使用的系统上,ARG_MAX比我在任何存储库中拥有的标记数高得多,所以我不介意限制,就像我在写“ ls * .jpg”时不介意的那样。 (2认同)
  • 最干净的解决方案 (2认同)
  • git config --global alias.prune-tags'!git tag -d $ {git tag)&amp;&amp; git fetch --tags'强制别名命令。请享用。:-) (2认同)
  • 谢谢,一个简单的问题有这么多令人费解的答案 (2认同)

Cha*_*ano 77

git fetch从v1.7.8开始,所有版本的Git都使用refspec,而自v1.9.0起,该--tags选项会覆盖该--prune选项.对于通用解决方案,请尝试以下方法:

$ git --version
git version 2.1.3

$ git fetch --prune origin "+refs/tags/*:refs/tags/*"
From ssh://xxx
 x [deleted]         (none)     -> rel_test
Run Code Online (Sandbox Code Playgroud)

有关如何在Git v1.9.0中更改"--tags"与"--prune"行为的更改,请参阅:https://github.com/git/git/commit/e66ef7ae6f31f246dead62f574cc2acb75fd001c

  • 这应该是最好的答案.它是一个单一的git命令,没有bash,没有管道,也没有xargs. (7认同)
  • 至少用git 2.18.0也可以使用这种语法:`git fetch --prune --prune-tags origin` (2认同)
  • 从git 2.17.0开始 - 包含了-prune-tags选项,并在PRUNING部分详细描述了以下文档中的等效命令:https://git-scm.com/docs/git-fetch/2.17. 0`git fetch origin --prune --prune-tags`或``git fetch origin --prune'refs/tags/*:refs/tags/*'`OR`git fetch <url of origin> --prune - prune-tags`或`git fetch <url of origin> --prune'refs/tags/*:refs/tags/*'` (2认同)

Mik*_*est 66

好问题.:)我没有完整的答案......

也就是说,您可以通过获取远程标签列表git ls-remote.要列出引用的存储库中的标记origin,您将运行:

git ls-remote --tags origin
Run Code Online (Sandbox Code Playgroud)

返回哈希和友好标签名称列表,如:

94bf6de8315d9a7b22385e86e1f5add9183bcb3c        refs/tags/v0.1.3
cc047da6604bdd9a0e5ecbba3375ba6f09eed09d        refs/tags/v0.1.4
...
2f2e45bedf67dedb8d1dc0d02612345ee5c893f2        refs/tags/v0.5.4
Run Code Online (Sandbox Code Playgroud)

你当然可以组合一个bash脚本来比较这个列表生成的标签和你本地的标签.看看git show-ref --tags,它以相同的形式生成标签名称git ls-remote).


顺便说一句,git show-ref有一个选项与你想要的相反.以下命令将列出远程分支上本地没有的所有标记:

git ls-remote --tags origin | git show-ref --tags --exclude-existing
Run Code Online (Sandbox Code Playgroud)

  • 如果你对一个复杂的剧本不感兴趣,Richard W的答案会更加优雅. (9认同)
  • 关于本地不存在的标签的旁注可以扩展以检查更多遥控器:`git remote | xargs -L 1 git ls-remote --tags | git show-ref --tags --exclude-existing` (2认同)
  • git 支持 --prune-tags。不确定这是引入的哪个版本。https://git-scm.com/docs/git-fetch#git-fetch---prune-tags (2认同)

Nic*_*rey 59

看起来像Git的近期版本(我在git v2.20上)只是简单地说

git fetch --prune --prune-tags
Run Code Online (Sandbox Code Playgroud)

更干净!

https://git-scm.com/docs/git-fetch#_pruning

  • 可以写成 `git fetch -pP` (5认同)
  • 自Git 2.17(2018年第二季度)起:/sf/answers/3445063331/ (4认同)

jok*_*ker 11

我知道我参加聚会迟到了,但现在有一个快速的答案:

git fetch --prune --prune-tags # or just git fetch -p -P
Run Code Online (Sandbox Code Playgroud)

是的,现在可以选择获取。

如果您不想获取,只需修剪:

git remote prune origin
Run Code Online (Sandbox Code Playgroud)


Ela*_*ute 9

在新的 git 版本中(如 v2.26.2)

-P, --prune-tags 如果启用了 --prune ,则在获取之前删除远程上不再存在的任何本地标签。应该更谨慎地使用此选项,与 --prune 不同,它会删除已创建的任何本地引用(本地标记)。此选项是提供显式标签 refspec 和 --prune 的简写,请参阅其文档中的讨论。

所以你需要运行:

git fetch origin --prune --prune-tags
Run Code Online (Sandbox Code Playgroud)

  • 请注意:我发现必须指定两个标志:--prune --prune-tags。--prune-tags 单独使用没有效果 (2认同)

imj*_*gel 7

这是一个很好的方法:

git tag -l | xargs git tag -d && git fetch -t

资料来源:demisx.GitHub.io


小智 7

Git本机支持清除本地标签:

git fetch --tags --prune
Run Code Online (Sandbox Code Playgroud)

该命令提取最新的标签,并删除所有已删除的标签。

  • 这在最新版本的Git中不起作用 (9认同)
  • 这将删除“_如果启用了`--prune`,则远程上不再存在的任何本地标签**_”。所以它应该是“git fetch --tags --prune --prune-tags”。这也会修剪其他引用,但据我所知,没有办法只修剪标签。无论如何,这个答案中的命令对我不起作用。(git版本2.32.0) (2认同)

Dan*_*non 6

与 @Richard W 的答案相同,但适用于 Windows (PowerShell)

git tag | ForEach-Object -Process { git tag -d $_ }
git fetch -t
Run Code Online (Sandbox Code Playgroud)


dot*_*raj 5

Show the difference between local and remote tags:

diff <(git tag | sort) <( git ls-remote --tags origin | cut -f2 | grep -v '\^' | sed 's#refs/tags/##' | sort)
Run Code Online (Sandbox Code Playgroud)
  • git tag gives the list of local tags
  • git ls-remote --tags gives the list of full paths to remote tags
  • cut -f2 | grep -v '\^' | sed 's#refs/tags/##' parses out just the tag name from list of remote tag paths
  • Finally we sort each of the two lists and diff them

以“ <”开头的行是您的本地标签,不再位于远程仓库中。如果数量很少,则可以一个接一个地手动删除它们;如果数量很多,则可以进行更多的grep-ing和管道操作以使其自动化。

  • 请考虑在代码中添加一些说明。这将最终改善您的答案的质量。 (2认同)

Aec*_*Liu 5

更新@2021/05

在此输入图像描述

$REPO将参数传递给自定义脚本。

内容为sync_git_tags.sh

#!/bin/sh

# cd to $REPO directory
cd $1
pwd

# sync remote tags
git tag -l | xargs git tag -d && git fetch -t
Run Code Online (Sandbox Code Playgroud)

老的

ps:更新于@2021/05,git fetch --prune --prune-tags origin在我的 MacOS 上不起作用。

我将该命令添加SourceTree为 MacOS 上的自定义操作。
设置Custom Actions方式Sourcetree-> Preferences...->Custom Actions


“要运行的脚本”必须是“git”路径。

我用来git fetch --prune --prune-tags origin将标签从远程同步到本地。

在此输入图像描述 在此输入图像描述