你如何重命名Git标签?

时间:2009-06-22 18:09:06

标签: git git-tag

今天我正在浏览一个项目的日志,并意识到我不久前发了一个标签名称。有没有办法重命名标签?谷歌没有发现任何有用的东西。

我意识到我可以检查标记版本并制作新标记,我甚至尝试过。但这似乎创建了一个不太正确的标签对象。一个人,

git tag -l

相对于所有其他标签,它不按顺序列出。我不知道这是否重要,但它让我相信新标签对象不是我想要的。我可以忍受这一点,因为我真的只关心标签名称与文档匹配,但我宁愿“正确”,假设有正确的方法来做到这一点。

11 个答案:

答案 0 :(得分:1828)

以下是将代码old重命名为new的方式:

git tag new old
git tag -d old
git push origin :refs/tags/old
git push --tags

push命令中的冒号从远程存储库中删除标记。如果你不这样做,Git会在你拉机时在机器上创建旧标签。

最后,确保其他用户删除已删除的标记。请告诉他们(同事)运行以下命令:

git pull --prune --tags

答案 1 :(得分:284)

最初的问题是如何重命名标记,这很容易:首先创建NEW作为OLD的别名:git tag NEW OLD然后删除OLD:git tag -d OLD

关于“Git方式”和(in)完整性的引用是基础的,因为它讨论的是保留标记名称,但使其引用不同的存储库状态。

答案 2 :(得分:106)

除了其他答案:

首先,您需要构建标记名称的别名,指向原始提交:

git tag new old^{}

然后你需要删除旧的本地

git tag -d old

然后删除远程位置上的标记:

# Check your remote sources:
git remote -v
# The argument (3rd) is your remote location,
# the one you can see with `git remote`. In this example: `origin`
git push origin :refs/tags/old

最后,您需要将新标记添加到远程位置。在您完成此操作之前,将不会添加

git push origin --tags

为每个远程位置迭代。

请注意,implications that a Git Tag change has给一个包的消费者!

答案 3 :(得分:27)

如果已发布,则无法将其删除(不存在被涂焦油和羽毛的风险)。 “Git方式”就是:

  

理智的事情。只是承认你搞砸了,并使用不同的名字。其他人已经看过一个标签名称,如果你保持相同的名称,你可能会遇到两个人都有“版本X”的情况,但他们实际上有不同的“X”。所以只需称它为“X.1”并完成它。

可替换地,

  

疯狂的事情。你真的想把新版本称为“X”,即使其他人已经看过旧版本。所以再次使用git-tag -f,好像你还没有发布旧版本一样。

这太疯狂了,因为:

  

Git没有(也不应该)改变用户背后的标签。所以如果有人已经得到了旧标签,那么在你的树上做一个git-pull就不应该让它们覆盖旧标签。

     

如果某人有你的发布标签,你不能只是通过更新自己的标签来更改标签。这是一个很大的安全问题,因为人们必须能够信任他们的标签名称。如果你真的想做疯狂的事情,你需要了解它,告诉别人你搞砸了。

所有礼貌man pages

答案 4 :(得分:24)

This wiki page有一个有趣的单行,它提醒我们,我们可以推动几个参考

git push origin <refs/tags/old-tag>:<refs/tags/new-tag> :<refs/tags/old-tag> && git tag -d <old-tag>
  

并要求其他克隆人执行git pull --prune --tags

所以我的想法就是推动:

    对于<new-tag>&gt;所引用的每次提交,
  • <old-tag<refs/tags/old-tag>:<refs/tags/new-tag>
  • the deletion of <old-tag>:<refs/tags/old-tag>

请参阅示例“Change naming convention of tags inside a git repository?”。

答案 5 :(得分:23)

作为对其他答案的补充,我添加了一个别名,只需一步即可完成所有操作,并带有更熟悉的* nix move命令。参数1是旧标记名称,参数2是新标记名称。

[alias]
    renameTag = "!sh -c 'set -e;git tag $2 $1; git tag -d $1;git push origin :refs/tags/$1;git push --tags' -"

用法:

git renametag old new

答案 6 :(得分:6)

对于喜欢冒险的人来说,可以在一个命令中完成:

mv .git/refs/tags/OLD .git/refs/tags/NEW

答案 7 :(得分:3)

不管处理推送标签和重命名已经推送的标签有什么问题,如果要重命名的标签是带有注释的标签,您都可以通过以下单行首先复制它命令行:

git tag -a -m "`git cat-file -p old_tag | tail -n +6`" new_tag old_tag^{}

然后,您只需要删除旧标签:

git tag -d old_tag

由于以下两个答案,我找到了此命令行:

修改:
使用标签的自动同步设置fetch.pruneTags=true(如https://stackoverflow.com/a/49215190/7009806中所述)时,我个人建议首先将新标签复制到服务器上,然后然后< / strong>删除旧的。这样,在删除旧标签时,新标签不会被随机删除,并且标签的同步会删除服务器上尚未存在的新标签。因此,例如,我们在一起得到:

git tag -a -m "`git cat-file -p old_tag | tail -n +6`" new_tag old_tag^{}
git push --tags
git tag -d old_tag
git push origin :refs/tags/old_tag

答案 8 :(得分:3)

此答案通过使用现有标签中的标签信息创建重复的带注释的标签(包括所有标签信息,如标签,消息和标签日期)来解决该问题。

SOURCE_TAG=old NEW_TAG=new; deref() { git for-each-ref \
"refs/tags/$SOURCE_TAG" --format="%($1)" ; }; \
GIT_COMMITTER_NAME="$(deref taggername)" \
GIT_COMMITTER_EMAIL="$(deref taggeremail)" \
GIT_COMMITTER_DATE="$(deref taggerdate)" git tag "$NEW_TAG" \
"$(deref "*objectname")" -a -m "$(deref contents)"

git tag -d old

git push origin new :old

更新SOURCE_TAGNEW_TAG值以匹配您的旧标签名和新标签名。

动机

据我所知,所有其他答案都有一些微妙的陷阱,或者没有完全复制有关标签的所有内容(例如,它们使用新的标签日期或当前用户的信息作为标签)。他们中的许多人都发出re-tagging警告,尽管这并不适用于这种情况(这是用于将标签名称移至其他提交,而不是重命名为其他名称的标签)。我已经做了一些挖掘工作,并且我相信我已经拼凑出了解决这些问题的解决方案。

目标

git-tag documentation指定带注释标签的部分。要真正实现无差别的重命名,这些元素在新标签中应该相同。

标记对象(用-a-s-u创建)称为“带注释”标记;它们包含创建日期,标记名称和电子邮件,标记消息以及可选的GnuPG签名。

在此答案中,我仅解决未签名的标签,尽管将解决方案扩展到已签名的标签很简单。

程序

示例中使用了一个名为old的带注释的标记,并将其重命名为new

步骤1:获取现有标签信息

首先,我们需要获取现有标签的信息。可以使用for-each-ref

命令:

git for-each-ref refs/tags --format="\
Tag name: %(refname:short)
Tag commit: %(objectname:short)
Tagger date: %(taggerdate)
Tagger name: %(taggername)
Tagger email: %(taggeremail)
Tagged commit: %(*objectname:short)
Tag message: %(contents)"

输出:

Tag commit: 88a6169
Tagger date: Mon Dec 14 12:44:52 2020 -0600
Tagger name: John Doe
Tagger email: <j.doe@example.com>
Tagged commit: cda5b4d
Tag name: old
Tag message: Initial tag

Body line 1.
Body line 2.
Body line 3.

步骤2:在本地创建重复的标签

可以使用步骤1中从现有标签收集的信息来创建具有新名称的重复标签。

提交ID和提交消息可以直接传递到git tag

可以使用git environment variables GIT_COMMITTER_NAMEGIT_COMMITTER_EMAILGIT_COMMITTER_DATE设置标记信息(名称,电子邮件和日期)。 On Backdating Tags文档中的git tag描述了这种情况下的日期用法;我通过实验发现了另外两个。

GIT_COMMITTER_NAME="John Doe" GIT_COMMITTER_EMAIL="j.doe@example.com" \
GIT_COMMITTER_DATE="Mon Dec 14 12:44:52 2020 -0600" git tag new cda5b4d -a -m "Initial tag

Body line 1.
Body line 2.
Body line 3."

两个标签的并排比较显示它们在所有重要方面都是相同的。唯一不同的是标记本身的提交引用,这是预期的,因为它们是两个不同的标记。

命令:

git for-each-ref refs/tags --format="\
Tag commit: %(objectname:short)
Tagger date: %(taggerdate)
Tagger name: %(taggername)
Tagger email: %(taggeremail)
Tagged commit: %(*objectname:short)
Tag name: %(refname:short)
Tag message: %(contents)"

输出:

Tag commit: 580f817
Tagger date: Mon Dec 14 12:44:52 2020 -0600
Tagger name: John Doe
Tagger email: <j.doe@example.com>
Tagged commit: cda5b4d
Tag name: new
Tag message: Initial tag

Body line 1.
Body line 2.
Body line 3.

Tag commit: 30ddd25
Tagger date: Mon Dec 14 12:44:52 2020 -0600
Tagger name: John Doe
Tagger email: <j.doe@example.com>
Tagged commit: cda5b4d
Tag name: old
Tag message: Initial tag

Body line 1.
Body line 2.
Body line 3.

作为一个命令,包括检索当前标签数据:

SOURCE_TAG=old NEW_TAG=new; deref() { git for-each-ref "refs/tags/$SOURCE_TAG" --format="%($1)" ; }; GIT_COMMITTER_NAME="$(deref taggername)" GIT_COMMITTER_EMAIL="$(deref taggeremail)" GIT_COMMITTER_DATE="$(deref taggerdate)" git tag "$NEW_TAG" "$(deref "*objectname")" -a -m "$(deref contents)"

步骤3:在本地删除现有标签

接下来,应在本地删除现有标签。如果您希望将旧标签与新标签一起保留(即复制标签而不是重命名),则可以跳过这一步。

git tag -d old

步骤4:将更改推送到远程存储库

假设您正在使用远程存储库,现在可以使用git push推送更改:

git push origin new :old

这将推入new标签,并删除old标签。

答案 9 :(得分:1)

简单的部分是重命名本地标签。更难的部分是远程部分。 这个技巧背后的想法是将旧标签/分支复制到新标签/分支并删除旧标签/分支,而无需结帐。

远程代码重命名/远程分支→代码转换(注意::refs/tags/

git push <remote_name> <old_branch_or_tag>:refs/tags/<new_tag> :<old_branch_or_tag>

远程分支重命名/远程标记→分支转换(注意::refs/heads/

git push <remote_name> <old_branch_or_tag>:refs/heads/<new_branch> :<old_branch_or_tag>

输出重命名远程标记:

D:\git.repo>git push gitlab App%2012.1%20v12.1.0.23:refs/tags/App_12.1_v12.1.0.23 :App%2012.1%20v12.1.0.23

Total 0 (delta 0), reused 0 (delta 0)
To https://gitlab.server/project/repository.git
 - [deleted]               App%2012.1%20v12.1.0.23
 * [new tag]               App%2012.1%20v12.1.0.23 -> App_12.1_v12.1.0.23

答案 10 :(得分:0)

对于一个或几个标签,请遵循3步方法。

步骤1:确定当前标签指向的提交的提交/对象ID

     command: git rev-parse <tag name>
     example: git rev-parse v0.1.0-Demo
     example output: db57b63b77a6bae3e725cbb9025d65fa1eabcde

第2步:从存储库中删除标签

     command: git tag -d <tag name>
     example: git tag -d v0.1.0-Demo
     example output: Deleted tag 'v0.1.0-Demo' (was abcde)

第3步:创建一个新标签,指向与旧标签所指向的提交ID相同的提交ID。

     command: git tag -a <tag name>  -m "appropriate message" <commit id>
     example: git tag -a v0.1.0-full  -m "renamed from v0.1.0-Demo" db57b63b77a6bae3e725cbb9025d65fa1eabcde
     example output: Nothing or basically <No error>

一旦本地git做好了标记名称更改的准备,就可以将这些更改推回原始位置,以供其他人使用。