578

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

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

第 2 个(第 3、第 4、...)用户现在具有不再反映在远程上的本地标签。

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

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

4

16 回答 16

1258

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

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

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

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

这些:

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

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

这甚至适用于 Windows。

于 2011-03-21T02:42:46.070 回答
281

从 Git v1.7.8 到 v1.8.5.6,你可以使用这个:

git fetch <remote> --prune --tags

更新

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

正如“Chad Juliano”所建议的,对于自 v1.7.8 以来的所有 Git 版本,您可以使用以下命令:

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

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

git fetch --prune <remote> "+refs/tags/*:refs/tags/*"
于 2013-05-01T00:39:18.457 回答
189

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

$ git tag -d $(git tag)

然后获取所有远程标签:

$ git fetch --tags
于 2014-10-09T15:40:40.170 回答
159

看起来最近版本的 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选项。例如,在从源而不是其他远程获取时始终修剪标签,

git config remote.origin.pruneTags true
于 2019-01-21T20:56:43.183 回答
85

自 v1.7.8以来的所有 Git 版本都可以git fetch通过 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

有关在 Git v1.9.0 中如何更改带有“--prune”行为的“--tags”的进一步阅读,请参阅:https ://github.com/git/git/commit/e66ef7ae6f31f246dead62f574cc2acb75fd001c

于 2014-12-02T16:42:48.517 回答
84

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

也就是说,您可以通过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
于 2009-12-04T15:43:17.487 回答
18

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

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

所以你需要运行:

git fetch origin --prune --prune-tags
于 2020-05-19T05:36:30.983 回答
14

Git 原生支持清理本地标签

git fetch --tags --prune-tags

此命令拉入最新标签并删除所有已删除的标签

于 2018-04-06T19:32:01.867 回答
12

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

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

是的,它现在是一个获取选项。

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

git remote prune origin
于 2020-04-22T15:36:13.037 回答
6

这是一个好方法:

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

来源:demisx.GitHub.io

于 2018-02-19T07:10:43.737 回答
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

老的

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

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


`Script to run` 必须是 `git` 路径。

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

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

于 2019-11-08T03:41:41.290 回答
4

显示本地标签和远程标签之间的区别:

diff <(git tag | sort) <( git ls-remote --tags origin | cut -f2 | grep -v '\^' | sed 's#refs/tags/##' | sort)
  • git tag给出本地标签列表
  • git ls-remote --tags给出远程标签的完整路径列表
  • cut -f2 | grep -v '\^' | sed 's#refs/tags/##'从远程标签路径列表中解析出标签名称
  • 最后,我们对两个列表中的每一个进行排序并区分它们

以“<”开头的行是您的本地标签,它们不再在远程仓库中。如果它们很少,您可以手动删除它们,如果它们很多,您可以进行更多的 grep-ing 和管道以使其自动化。

于 2014-10-15T19:04:07.937 回答
3

刚刚在 GitHub 上的 pivotal_git_scripts Gem fork 中添加了一个 git sync-local-tags 命令:

https://github.com/kigster/git_scripts

安装 gem,然后在您的存储库中运行“git sync-local-tags”以删除远程不存在的本地标签。

或者,您可以在下面安装此脚本并将其称为“git-sync-local-tags”:


#!/usr/bin/env ruby

# Delete tags from the local Git repository, which are not found on 
# a remote origin
#
# Usage: git sync-local-tags [-n]
#        if -n is passed, just print the tag to be deleted, but do not 
#        actually delete it.
#
# Author: Konstantin Gredeskoul (http://tektastic.com)
#
#######################################################################

class TagSynchronizer
  def self.local_tags
    `git show-ref --tags | awk '{print $2}'`.split(/\n/)
  end

  def self.remote_tags
    `git ls-remote --tags origin | awk '{print $2}'`.split(/\n/)
  end

  def self.orphaned_tags
    self.local_tags - self.remote_tags
  end

  def self.remove_unused_tags(print_only = false)
    self.orphaned_tags.each do |ref|
      tag = ref.gsub /refs\/tags\//, ''
      puts "deleting local tag #{tag}"
      `git tag -d #{tag}` unless print_only
    end
  end
end

unless File.exists?(".git")
  puts "This doesn't look like a git repository."
  exit 1
end

print_only = ARGV.include?("-n")
TagSynchronizer.remove_unused_tags(print_only)
于 2010-12-14T20:57:49.943 回答
2

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

git tag | foreach-object -process { git tag -d $_ }
git fetch -t
于 2019-04-06T18:37:27.400 回答
1

怎么样 - 删除所有本地标签然后重新获取?考虑到您的仓库可能包含子模块:

git submodule foreach --recursive  'git tag | xargs git tag -d'
(alternatively, "for i in `find .git  -type d -name '*tags*'`; do rm -f $i/*;  done")
git fetch -t
git submodule foreach --recursive git fetch -t
于 2014-09-09T19:34:34.500 回答
1

TortoiseGit 现在可以比较标签了。

左日志在远程,右日志在本地。

在此处输入图像描述

使用同步对话框的比较标签功能:

在此处输入图像描述

另见TortoiseGit 问题 2973

于 2017-07-14T09:12:39.097 回答