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

问题描述 投票:400回答:13

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

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

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

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

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

git git-tag
13个回答
63
投票

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

也就是说,您可以通过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

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)

2
投票

TortoiseGit现在可以比较标签。

左侧日志位于远程,右侧位于本地。

enter image description here

使用“同步”对话框的“比较标记”功能

enter image description here

另见TortoiseGit issue 2973


1
投票

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

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

1
投票

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

git tag | foreach-object -process { git tag -d $_ }
git fetch -t

938
投票

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

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

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

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

这些:

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

这甚至适用于Windows。


225
投票

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

git fetch <remote> --prune --tags

Update

由于提交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/*"

144
投票

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

$ git tag -d $(git tag)

然后获取所有远程标签:

$ git fetch --tags

74
投票

自v1.7.8以来所有版本的Git都使用refspec了解git fetch,而自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


31
投票

看起来像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

7
投票

这是一个很好的方法:

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

资料来源:demisx.GitHub.io


7
投票

Git本身支持清理本地标记:

git fetch --tags --prune

此命令会提取最新的标记并删除所有已删除的标记。


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和管道来自动化它。

© www.soinside.com 2019 - 2024. All rights reserved.