我们在git中使用标签作为部署过程的一部分。有时,我们希望通过从远程存储库中删除它们来清理这些标记。
这非常简单。一个用户在一组命令中删除本地标签和远程标签。我们有一个结合了两个步骤的小shell脚本。
第二个(第3个,第4个......)用户现在拥有不再反映在遥控器上的本地标签。
我正在寻找类似于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 ls-remote --tags origin | git show-ref --tags --exclude-existing
刚刚在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)
怎么样 - 删除所有本地标签,然后重新获取?考虑到您的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
与@Richard W相同的答案,但对于Windows(PowerShell)
git tag | foreach-object -process { git tag -d $_ }
git fetch -t
这是一个很好的问题,我一直想知道同样的事情。
我不想写一个脚本,所以寻求一个不同的解决方案。关键是发现你可以在本地删除标签,然后使用git fetch从远程服务器“取回”。如果遥控器上不存在该标签,则它将保持删除状态。
因此,您需要按顺序键入两行:
git tag -l | xargs git tag -d
git fetch --tags
这些:
这甚至适用于Windows。
从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/*"
如果您只想要遥控器上存在的那些标签,只需删除所有本地标签:
$ git tag -d $(git tag)
然后获取所有远程标签:
$ git fetch --tags
自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
看起来像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
Git本身支持清理本地标记:
git fetch --tags --prune
此命令会提取最新的标记并删除所有已删除的标记。
显示本地和远程标记之间的区别:
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和管道来自动化它。