如何删除已经推送的 Git 标签?
26 回答
您可以推送对远程标记名称的“空”引用:
git push origin :tagname
或者,更明确地说,使用该--delete
选项(或者-d
如果您的 git 版本早于 1.8.0):
git push --delete origin tagname
请注意,git 具有标签命名空间和分支命名空间,因此您可以为分支和标签使用相同的名称。如果要确保不会意外删除分支而不是标记,可以指定永远不会删除分支的完整 ref:
git push origin :refs/tags/tagname
如果您还需要删除本地标签,请使用:
git tag --delete tagname
背景
将分支、标签或其他引用推送到远程存储库涉及指定“哪个存储库、什么源、什么目标?”
git push remote-repo source-ref:destination-ref
将 master 分支推送到源的 master 分支的真实示例是:
git push origin refs/heads/master:refs/heads/master
由于默认路径,可以缩短为:
git push origin master:master
标签的工作方式相同:
git push origin refs/tags/release-1.0:refs/tags/release-1.0
也可以缩短为:
git push origin release-1.0:release-1.0
通过省略源引用(冒号之前的部分),您将“无”推送到目标,删除远程端的引用。
更直接的方法是
git push --delete origin YOUR_TAG_NAME
在这种情况下,IMO 前缀冒号语法有点奇怪
如果您有v0.1.0
要删除的远程标签,而您的远程是origin
,那么只需:
git push origin :refs/tags/v0.1.0
如果还需要在本地删除标签:
git tag -d v0.1.0
有关 Git 异常删除语法的解释,请参阅Adam Franco的回答。:
删除所有本地标签并获取远程标签列表:
git tag -l | xargs git tag -d
git fetch
删除所有远程标签
git tag -l | xargs -n 1 git push --delete origin
清理本地标签
git tag -l | xargs git tag -d
要从远程存储库中删除标签:
git push --delete origin TAGNAME
您可能还想在本地删除标签:
git tag -d TAGNAME
git push --delete origin $TAGNAME
是正确的方法(除了本地删除)。
但是:确保使用 Git 2.31。
" git push $there --delete
" ( man )应该被诊断为错误,而是变成了匹配的推送,已在 Git 2.31 (Q1 2021) 中更正。
请参阅Junio C Hamano ( ) 的提交 20e4164(2021 年 2 月 23 日)。(由Junio C Hamano 合并 -- --在提交 1400458中,2021 年 2 月 25 日)gitster
gitster
push
: 不要把 --delete '' 变成匹配的推送通知人:蒂尔曼·沃格尔
当我们将语法糖“
git push remote --delete
” (man)<ref>
添加到“git push
” (man)作为规范(man)的同义词时:语法在f517f1f ( “ :(man)作为:foo”的语法糖,2009-12-30, Git v1.7.0-rc0 -- merge),我们没有足够小心以确保它不为空。git push remote
builtin-push
add
--delete
<ref>
盲目地将“--delete”重写为“:”意味着一个空字符串
<ref>
会导致refspec“:”,这是请求“匹配”推送的语法,它不会删除任何内容。更糟糕的是,如果有匹配的 ref 可以快进,即使用户觉得他们还没有准备好被推出,它们也会过早发布,这将是一场真正的灾难。
从您的终端执行以下操作:
git fetch
git tag
git tag -d {tag-name}
git push origin :refs/tags/{tag-name}
现在去 Github.com 刷新一下,它们就消失了。
请注意,如果您有一个名为远程标记的远程分支,则这些命令是不明确的:
git push origin :tagname
git push --delete origin tagname
所以你必须使用这个命令来删除标签:
git push origin :refs/tags/<tag>
而这个删除分支:
git push origin :refs/heads/<branch>
如果没有,您将收到如下错误:
error: dst refspec <tagname> matches more than one.
error: failed to push some refs to '<repo>'
处理数千个远程标签的方法速度提高 100 倍
在需要删除超过 11,000 个标签的情况下阅读这些答案后,我了解到这些方法依赖或xargs
花费的时间太长,除非你有几个小时可以刻录。
苦苦挣扎,我找到了两种更快的方法。对于这两者,从git tag
或git ls-remote --tags
列出要在遥控器上删除的标签。在下面的示例中,您可以省略或替换为您想要sorting_proccessing_etc
的任何grep
ing、sort
ing、tail
ing 或head
ing(例如 grep -P "my_regex" | sort | head -n -200
等):
第一种方法是迄今为止最快的,可能比使用快20 到 100 倍xargs
,并且一次至少可以处理数千个标签。
git push origin $(< git tag | sorting_processing_etc \
| sed -e 's/^/:/' | paste -sd " ") #note exclude "<" for zsh
这是如何运作的?正常的、行分隔的标签列表被转换为单行以空格分隔的标签,每个标签都以:
so 开头。. .
tag1 becomes
tag2 ======> :tag1 :tag2 :tag3
tag3
git push
与此格式标签一起使用不会将任何内容推送到每个远程引用中,将其删除(以这种方式推送的正常格式是local_ref_path:remote_ref_path
)。
方法二在同一页面的其他地方作为单独的答案分解
在这两种方法之后,您可能还想删除本地标签。这要快得多,所以我们可以回到使用xargs
and git tag -d
,这就足够了。
git tag | sorting_processing_etc | xargs -L 1 git tag -d
或类似于远程删除:
git tag -d $(< git tag | sorting_processing_etc | paste -sd " ")
如果您使用 SourceTree - 一个很棒的 Git GUI - 那么您可以通过执行以下操作轻松完成此操作而无需命令行:
- 在 SourceTree 中打开您的存储库
- 选择并展开左侧的“标签”选项卡
- 右键单击要删除的标签
- 选择“删除 YOUR_TAG_NAME”
- 在验证窗口中,选择“Remove Tag From Remotes”
YOUR_TAG_NAME 现在将从您的本地存储库和所有远程存储库中删除 - 无论是 GitHub、BitBucket 还是您列为该存储库的远程存储库的任何其他位置。
此外,如果您在本地删除了一个标签,但没有在远程源上删除,并且您想在任何地方删除它,那么只需创建一个具有相同名称并附加在与源相同的提交处的新标签。然后,重复上述步骤以删除所有位置。
如果您release01
在 Git 存储库中创建了一个名为的标记,则可以通过执行以下操作将其从存储库中删除:
git tag -d release01
git push origin :refs/tags/release01
要从 Mercurial 存储库中删除一个:
hg tag --remove featurefoo
请参考https://confluence.atlassian.com/pages/viewpage.action?pageId=282175551
正如@CubanX 所建议的那样,我已将这个答案与我原来的答案分开:
这是一种比它快几倍的方法,xargs
并且可以通过调整来扩展更多。它使用Github API(个人访问令牌)并利用该实用程序parallel
。
git tag | sorting_processing_etc | parallel --jobs 2 curl -i -X DELETE \
https://api.github.com/repos/My_Account/my_repo/git/refs/tags/{} -H
\"authorization: token GIT_OAUTH_OR_PERSONAL_KEY_HERE\" \
-H \"cache-control: no-cache\"`
parallel
有许多操作模式,但通常并行化你给它的任何命令,同时允许你设置进程数量的限制。您可以更改--jobs 2
参数以允许更快的操作,但我遇到了 Github 的速率限制问题,目前为 5000/小时,但似乎也有一个未记录的短期限制。
在此之后,您可能还想删除本地标签。这要快得多,所以我们可以回到使用xargs
and git tag -d
,这就足够了。
git tag | sorting_processing_etc | xargs -L 1 git tag -d
我想删除所有标签,除了那些与模式匹配的标签,这样我就可以删除除了最后几个月的生产标签之外的所有标签,这就是我曾经取得巨大成功的方法:
删除所有远程标签并从删除中排除表达式
git tag -l | grep -P '^(?!Production-2017-0[89])' | xargs -n 1 git push --delete origin
删除所有本地标签并从删除中排除表达式
git tag -l | grep -P '^(?!Production-2017-0[89])' | xargs git tag -d
如果您使用的是 PowerShell,并且想要删除其中的一堆:
# Local tags:
git tag -l | foreach { git tag -d $_ }
# Remote tags:
git tag -l | foreach { git push --delete origin $_ }
当然,您也可以在删除之前对其进行过滤:
git tag -l | Where-Object { $_ -like "build-*" } | foreach { git tag -d $_ }
其他答案指出了如何实现这一点,但您应该记住后果,因为这是一个远程存储库。
git tag 手册页,在On Retagging部分,很好地解释了如何礼貌地通知远程 repo 的其他用户所做的更改。他们甚至提供了一个方便的公告模板,用于传达其他人应该如何获得您的更改。
从本地和原始位置删除给定标签的简单脚本。检查标签是否真的存在。
if [ $(git tag -l "$1") ]; then
git tag --delete $1
git push --delete origin $1
echo done.
else
echo tag named "$1" was not found
fi
如何使用:
- 创建 shell 脚本文件(例如 git-tag-purge.sh)并粘贴内容。
- chmod 您的脚本文件以使其可执行。
- 使脚本全局可用
- cd 到你的 git 项目
- 调用脚本(例如
$>git-tag-purge.sh tag_name
)
对于 Tortoise git 用户,在数百个标签的规模下,您可以使用 UI 一次删除多个标签,但 UI 很好地隐藏在上下文菜单下。
在资源管理器窗口中右键单击 -> 浏览引用 -> 右键单击 ref/refmotes/name -> 选择“删除远程标签”
见https://tortoisegit.org/docs/tortoisegit/tgit-dug-browse-ref.html
似乎xargs
已经做了很多工作。回顾这个线程,我猜xargs
你所经历的缓慢是因为在xargs -n 1
不需要时使用的原始答案。
这等效于您的方法一,除了xargs
自动处理最大命令行长度:
git tag | sorting_processing_etc | xargs git push --delete origin
xargs
也可以并行运行进程。方法2 xargs
:
git tag | sorting_processing_etc | xargs -P 5 -n 100 git push --delete origin
以上使用最多 5 个进程来处理每个进程中最多 100 个参数。您可以尝试使用这些参数来找到最适合您需求的方法。
如果您创建了一个以#字符开头的标签,例如#ST002
,您可能会发现您无法使用普通模式删除。IE
git tag -d #STOO2
不会删除标签,而是像这样将其包装在字符串文字中
git tag -d "#ST002" or git tag -d '#ST002'
这样就可以删除了。希望它能帮助那些错误地使用#来编写标签名称的人。
只是想分享一个我创建的别名,它做同样的事情:
将以下内容添加到您的~/.gitconfig
[alias]
delete-tag = "!f() { \
echo 'deleting tag' $1 'from remote/origin ausing command: git push --delete origin tagName;'; \
git push --delete origin $1; \
echo 'deleting tag' $1 'from local using command: git tag -d tagName;'; \
git tag -d $1; \
}; f"
用法如下:
-->git delete-tag v1.0-DeleteMe
deleting tag v1.0-DeleteMe from remote/origin ausing command: git push --delete origin tagName;
To https://github.com/jsticha/pafs
- [deleted] v1.0-DeleteMe
deleting tag v1.0-DeleteMe from local using command: git tag -d tagName;
Deleted tag 'v1.0-DeleteMe' (was 300d3ef22)
要删除远程存储库上的标签,您可以使用
git push <remote> :refs/tags/<tagname>
上面的解释方法是将其读取为空值,冒号之前的值被推送到远程标签名称。
这是一个本地测试用例,可以在本地测试它而不会弄乱远程:
~/p $ mkdir gittest
~/p/git $ cd gittest/
~/p/gittest $ git init
Initialized empty Git repository in /Users/local_user/p/gittest/.git/
~/p/gittest $ touch testfile.txt
~/p/gittest $ git add testfile.txt
~/p/gittest $ git commit -m "initial commit"
[master (root-commit) 912ce0e] initial commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 testfile.txt
~/p/gittest $ git tag
~/p/gittest $ git tag -a testtag
~/p/gittest $ git tag
testtag
~/p/gittest $ git show-ref
912ce0e40635c90241fdab756dce7ea34938de57 refs/heads/master
b0a6c15cabb990e6d6c46f762891b63608d962f3 refs/tags/testtag
~/p/gittest $ cd ..
~/p $ mkdir gitbare
~/p $ cd gitbare
~/p/gitbare $ git init --bare
Initialized empty Git repository in /Users/local_user/p/gitbare/
~/p/gitbare $ cd ..
~/p $ cd gittest/
~/p/gittest $ git remote add origin /Users/local_user/p/gitbare
~/p/gittest $ git push -u origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 215 bytes | 215.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /Users/local_user/p/gitbare
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
~/p/gittest $ git push origin testtag
Counting objects: 1, done.
Writing objects: 100% (1/1), 163 bytes | 163.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To /Users/local_user/p/gitbare
* [new tag] testtag -> testtag
~/p/gittest $ git show-ref
912ce0e40635c90241fdab756dce7ea34938de57 refs/heads/master
912ce0e40635c90241fdab756dce7ea34938de57 refs/remotes/origin/master
b0a6c15cabb990e6d6c46f762891b63608d962f3 refs/tags/testtag
~/p/gittest $ git push -d origin testtag
To /Users/local_user/p/gitbare
- [deleted] testtag
~/p/gittest git tag -d testtag
Deleted tag 'testtag' (was b0a6c15)
~/p/gittest $ git show-ref
912ce0e40635c90241fdab756dce7ea34938de57 refs/heads/master
912ce0e40635c90241fdab756dce7ea34938de57 refs/remotes/origin/master
~/p/gittest
这两个步骤工作正常:
# delete local tag '1.0.0'
git tag -d 1.0.0
# delete remote tag '1.0.0' (eg, GitHub version too)
git push origin :refs/tags/1.0.0
这对我有用
git push --force origin refs/tags/<tag_name>:refs/tags/<tag_name>