删除不在远程存储库上的本地标签

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

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

第二(第三,第四,…)用户现在具有不再反映在远端的本地标签。

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

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

好问题。 :)我没有一个完整的答案…

也就是说,你可以通过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 show-ref有一个选项,它和你想要的相反。 以下命令将列出远程分支上本地没有的所有标记:

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

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

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

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

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

这些:

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

  2. 从远程回购获取所有有效标签。

这甚至可以在Windows上工作。

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

 git fetch <remote> --prune --tags 

更新

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

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

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

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

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

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

 $ git tag -d $(git tag) 

然后获取所有的远程标签:

 $ git fetch --tags 

从v1.7.8开始的所有版本的git fetch都能理解git fetch ,但是从v1.9.0开始,– --tags选项将覆盖--prune选项。 对于一个通用的解决scheme,试试这个:

 $ 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

刚刚添加了git sync-local-tags命令到pivotal_git_scripts Gem fork在GitHub上:

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) 

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

 diff <(git tag | sort) <( git ls-remote --tags origin | cut -f2 | grep -v '\^' | sed 's#refs/tags/##' | sort) 
  • git tag给出了本地标签的列表
  • git ls-remote --tags给出远程标签的完整path列表
  • cut -f2 | grep -v '\^' | sed 's#refs/tags/##' cut -f2 | grep -v '\^' | sed 's#refs/tags/##'只是从远程标签path列表中parsing出标签名称
  • 最后我们对这两个列表中的每一个进行sorting,

以“<”开头的行是您的本地标签,不再位于远程仓库中。 如果它们很less,可以逐个手动删除它们,如果它们很多,则可以使用更多的选项和pipe道来自动化。

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

 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 

TortoiseGit现在可以比较标签。

左边的日志是远程的,右边是本地的。

在这里输入图像描述

使用同步对话框的比较标记function:

在这里输入图像描述

另请参阅TortoiseGit问题2973