删除本地git标签,这些标签已不在远程仓库中。

670
我们在git中使用标签作为部署过程的一部分。有时,我们想通过从远程仓库中删除它们来清理这些标签。
这很简单。一个用户可以使用一组命令删除本地标签和远程标签。我们有一个小的shell脚本将这两个步骤结合起来。
第二个(第三个、第四个……)用户现在拥有本地标签,这些标签不再反映在远程上。
我正在寻找类似于“git remote prune origin”的命令,用于清理已删除远程分支的本地跟踪分支。
或者,可以使用一个简单的列出远程标签的命令来与通过“git tag -l”返回的本地标签进行比较。

3
我在Git中提出了一个新功能,支持修剪过时的标签:http://thread.gmane.org/gmane.comp.version-control.git/168833。 - Adam Monsen
7
注意:从 Git 2.17 版本开始(即2018年第二季度),使用命令 git config fetch.pruneTags true 即可使你的 git fetch 命令按照你的意愿执行!请参阅我在另一个问题中的答案 - VonC
11
以下是重新发布的一条评论:至少从 git 2.18.0 开始,还可以使用这个语法:git fetch --prune --prune-tags origin - zutnop
16个回答

1347

这是个好问题,我也一直在想同样的事情。

我不想写脚本,所以寻求了不同的解决方案。关键在于发现你可以在本地删除一个标签,然后使用 git fetch 从远程服务器“获取”它。如果这个标签在远程不存在,那么它就会保持被删除状态。

因此,你需要输入两行命令:

git tag -l | xargs git tag -d
git fetch --tags

这些:

  1. 从本地仓库中删除所有标签。顺便说一句,xargs会将“tag -l”输出的每个标签放在“tag -d”的命令行上。 如果没有这个,git不会删除任何东西,因为它不读取stdin(愚蠢的git)。

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

这甚至在Windows上也可以正常工作。


34
正如另一个答案中所指出的那样,这将删除所有本地标签,并且不在远程仓库中的标签显然不会被重新创建。 - second
4
第一个命令需要一个 xargs 扩展或者其他什么东西吗?当我在 Windows 命令提示符中执行该命令时,会收到以下错误信息:'xargs' 不是内部或外部命令,也不是可运行的程序或批处理文件。 - Web_Designer
20
这应该是完全不必要的。应该有一个 git tag prune origin 命令。 - void.pointer
9
这种方法可能不适用于每个人。为了保险起见,你应该执行 git fetch --tags 命令。 - Adam Kurkiewicz
13
在PowerShell中,我不得不运行 git tag -l | %{git tag -d $_} 才能使这个工作。不确定其他人是否会有同样的情况。 - Alain
显示剩余9条评论

328

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

git fetch <remote> --prune --tags

更新

这在较新的 Git 版本(从 v1.9.0 开始)上已不再适用,因为有一个名为 e66ef7ae6f31f2 的提交。但是我并不想将其删除,因为对某些人来说确实有效。

根据“Chad Juliano”的建议,在所有 Git 版本(自 v1.7.8 起)中,您可以使用以下命令:

git fetch --prune <remote> +refs/tags/*:refs/tags/*

为了避免通配符扩展(例如在 Windows 上),您可能需要用引号将标签部分括起来:

git fetch --prune <remote> "+refs/tags/*:refs/tags/*"

注意:在所有这些情况下,可能会是"origin"或你通常引用的任何远程主机名。


2
我指的是随 Git for Windows 1.9.4-preview20140611 打包的文档(我怀疑所有之前的版本也是如此)。 我使用 "git fetch --help" 访问该文档。 [quote] 如果仅因为默认标签自动跟随或由于 --tags 选项而获取标签,则不会删除标签。[/quote] - Félix Cantournet
3
git fetch --prune <remote> +refs/tags/*:refs/tags/* 在 ZSH 中无法工作,但在 BASH 中可以。 - Alex
4
@Alex这只是因为zsh会扩展*,但如果你用单引号引起来,应该就没问题了。 - NSF
16
自Git 2.17.0版本开始,git提供了一个名为--prune-tags的快捷方式,其在文档的PRUNING章节中有描述。--prune-tags选项相当于在远程的refspecs中声明refs/tags/*:refs/tags/*。等价命令包括: git fetch origin --prune --prune-tagsgit fetch origin --prune 'refs/tags/*:refs/tags/*'git fetch <url of origin> --prune --prune-tagsgit fetch <url of origin> --prune 'refs/tags/*:refs/tags/*' - mkisaacs
13
git fetch origin --prune --prune-tags可以同时清除远程跟踪分支和标签。该功能在Git 2.18版本中被引入。 - Number945
显示剩余8条评论

301

看起来最近的 Git 版本(我使用的是 git v2.20)允许我们简单地执行以下操作:

git fetch --prune --prune-tags

更加整洁!

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

您还可以配置Git在获取时始终修剪标签:

git config fetch.pruneTags true

如果你只想在从特定远程获取时修剪标签,你可以使用remote.<remote>.pruneTags选项。例如,要始终从"origin"获取时修剪标签但不修剪其他远程的标签,

git config remote.origin.pruneTags true

太好了。我已经适应了在SOes上发布 -> ¿Cómo puedo eliminar las etiquetas de Git que solo tengo en local? - fedorqui
太好了!我遇到了“git-shell died of signal 13”的git push失败。即使增加了http.postbuffer也没有效果。启用GIT_TRACE_PACKET和GIT_TRACE后,我发现推送到无效的refs/tags,所以使用“--prune-tags”解决了这个问题。非常感谢! - Ivellios
4
可以写成 git fetch -pP - pooya13
请注意,这也会修剪本地分支 编辑 我使用的是2.19.2.windows.1版本。 - Nathan Adams
3
git fetch --prune-tags 没有生效。我们总是需要同时删除标签和分支吗?如果我不想删除分支怎么办?谢谢。 - Rafs
新版本的Git可能存在一个bug。我的2.39.2版本在使用--prune-tags参数时无法进行修剪,尽管使用说明中建议这样做。我不得不启用了fetch.pruneTags选项才能成功删除一个过期的标签。O_o - stefanct

201

如果你只想要那些在远程存在的标签,那么只需删除所有本地标签:

$ git tag -d $(git tag)

然后获取所有远程标签:

$ git fetch --tags

4
@ocroquette,我不确定它比“xargs”更好在哪里。如果您具有比“ARG_MAX”或类似限制更多的标记,则此方法将无法正常工作。虽然这种情况不太可能发生,但这也是为什么“xargs”非常优秀的原因。 - Paul Draper
3
“好看”是一个主观的事情,每个人都会有自己的看法。关于ARG_MAX,那是正确的。然而,在我使用的系统上,ARG_MAX比我在任何仓库中拥有的标签数要高得多,因此我并不介意这个限制,就像我写“ls *.jpg”一样也不介意。 - ocroquette
3
强制别名命令。享受吧。 :-)git config --global alias.prune-tags '!git tag -d $(git tag) && git fetch --tags' - Karl Wilbur

86

自 Git v1.7.8 以来的所有版本都能理解包含 refspec 的git fetch,而自 Git 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

如欲深入了解 Git v1.9.0 中 "--tags" 与 "--prune" 行为的变更,请参阅:https://github.com/git/git/commit/e66ef7ae6f31f246dead62f574cc2acb75fd001c


1
origin 替换为 upstream,然后 Git 根据上游修正了我的本地标签;接下来,git push origin :<deleted-tag-name> 更新了我的 GitHub 分支,删除了已删除的标签。 - leanne
3
至少从git 2.18.0版本开始,也可以使用以下语法:git fetch --prune --prune-tags origin - Martin
4
从 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/*' git fetch <url of origin> --prune --prune-tags git fetch <url of origin> --prune 'refs/tags/*:refs/tags/*' - mkisaacs

83

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

话虽如此,您可以通过git ls-remote获取远程标签列表。 要列出由origin引用的仓库中的标记,您需要运行:

git ls-remote --tags origin

这会返回一个由哈希和友好标记名称组成的列表,例如:

94bf6de8315d9a7b22385e86e1f5add9183bcb3c        refs/tags/v0.1.3
cc047da6604bdd9a0e5ecbba3375ba6f09eed09d        refs/tags/v0.1.4
...
2f2e45bedf67dedb8d1dc0d02612345ee5c893f2        refs/tags/v0.5.4

你可以编写一个bash脚本来比较这个列表生成的标签和你本地拥有的标签。请查看git show-ref --tags,它以与git ls-remote相同的形式生成标签名称。


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

git ls-remote --tags origin | git show-ref --tags --exclude-existing

14
Richard W的回答更加优雅,如果您不想要一个复杂的脚本的话。 - Kyle Heironimus
2
关于本地不存在标签的侧记可以扩展到检查更多的远程仓库: git remote | xargs -L 1 git ls-remote --tags | git show-ref --tags --exclude-existing - Palec
2
git支持--prune-tags选项。不确定是在哪个版本引入的。https://git-scm.com/docs/git-fetch#git-fetch---prune-tags - John Kloian

38

在新的git版本(如v2.26.2或更高版本)中,您可以使用--prune-tags

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

因此,您需要运行:

git fetch origin --prune --prune-tags

2
作为一条注释:我发现必须同时指定两个标志:--prune 和 --prune-tags。单独使用 --prune-tags 是没有效果的。 - Wild Pottok

14

Git本地标签的清理是原生支持的

git fetch --tags --prune-tags

这条命令会拉取最新的标签,并删除所有已删除的标签


1
看起来应该是"--prune"而不是"--prune-tags",否则这就是我需要的,谢谢。 - AnyDev
我在使用SourceTree时遇到了问题,无法推送一些引用...:这对我有效 :) 非常感谢 - Abhishek Thapliyal
@AnyDev:--prune-tags 是正确的。man页面关于 --prune 的说明是:如果标签仅因默认标签自动跟踪或 --tags 选项而被获取,则不会对其进行修剪。 - David Ongaro
1
如果启用了 --prune,则此操作将删除“_在远程不存在的任何本地标签_”。因此应该使用 git fetch --tags --prune --prune-tags。这也会修剪其他引用,但据我所知,没有办法仅修剪标签。无论如何,此答案中的命令对我不起作用。(git 版本 2.32.0) - wovano
这对我没有起作用。我还需要通过 git fetch --prune --prune-tags 剪枝分支。我的 git 版本是2.37.3。不确定 git fetch --tags --prune --prune-tags 是否会忽略剪枝分支? - Rafs

12

我知道我来晚了,但现在有一个快速的答案:

git fetch --prune --prune-tags # or just git fetch -p -P

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

如果你不想获取,只想修剪:

git remote prune origin

7

这是一种好的方法:

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

来源:demisx.GitHub.io


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接