删除不在远程存储库上的本地标签
我们在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
这些:
-
删除本地存储库中的所有标签。 FWIW,xargs将“tag -l”的每个标签输出放在“tag -d”的命令行上。 没有这个,git不会删除任何东西,因为它不读取标准input(愚蠢的git)。
-
从远程回购获取所有有效标签。
这甚至可以在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