如何重命名Git标签?


1219

今天,我在日志中寻找一个项目,并意识到一段时间前我曾用手指来命名标签。有什么办法可以重命名标签?Google并未提供任何有用的信息。

我意识到我可以签出加标签的版本并制作一个新标签,我什至尝试了。但这似乎创建了一个不太正确的标记对象。一方面

git tag -l

相对于所有其他标签无序列出它。我不知道这是否有意义,但是这让我相信新的标记对象并不是我想要的。我可以接受这一点,因为我真的只关心标签名称是否与文档匹配,但是我宁愿“正确”地进行操作,前提是可以找到正确的方法。


您是否使用了相同的调用,即如果旧标签是带注释/签名标签,新标签是否也属于此类,还是轻量级标签?
2009年

1
错误的旧标签和所需的新标签都应添加注释并取消签名。旧标签是使用'git tag -a bad_tag_name'创建的,因此我想按照'git tag -a good_tag_name'的方式进行操作。
布兰登·福斯迪克2009年

我应该指出,我也希望这个神奇的标签重命名过程能够保留正在重命名的标签中的注释。实际上,我真的很想更改名称,而别无其他。
布兰登·福斯迪克2009年

7
git log --oneline --decorate --graph在清理标签时很有帮助。
乔尔·普拉

您可以在一行中重命名标签:请参阅下面的答案
VonC 2014年

Answers:


2037

这是将标签重命名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

请注意,如果要更改带注释的标记,则需要确保新标记名称引用的是基础提交,而不是要删除的旧带注释的标记对象。因此,请使用git tag -a new old^{}而不是git tag new old(这是因为带注释的标签是对象,而轻量级标签不是对象,有关此信息,请参见)。


19
如果标记了注释,则新标记将不会包含旧标记的消息,但这是有用的信息
NickSoft,2011年

25
@NickSoft,我只是使用带注释的标签完成了上述操作。消息从旧复制到新就好了。也许我有较新版本的git?
katyhuff

25
git push origin :refs/tags/oldgit push origin :old我可以简化为。
Jesse Glick 2014年

25
我建议更改“ git push --tags”,使其对此标签“ git push origin refs / tags / new”更明确。您不想无意间推送其他标签。
2014年

11
警告:使用git tag new old将会创建一个指向旧标签的标签,而不是旧标签的提交。(请参阅为什么我不能从Git GUI签出我的标签?
Stevoisiak,

297

原来的问题是如何改标签,这是很容易:首先创建新的旧的别名:git tag NEW OLD然后删除旧:git tag -d OLD

关于“ Git方式”和(混乱)理性的引用是不合时宜的,因为它是在谈论保留标签名称,但使之指向不同的存储库状态。


3
上面的答案稍微有点可取,因为它包括git push origin业务。
Roly 2013年

最简单的办法,工作极大地重命名Gitflow创造了一个以前的版本标签
RousseauAlexandre

5
警告:使用git tag new old将会创建一个指向旧标签的标签,而不是旧标签的提交。(请参阅为什么我不能从Git GUI签出我的标签?
Stevoisiak,

118

除了其他答案:

首先,你需要建立一个别名了的标签名称,指向原来的承诺:

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

遍历每个远程位置。

请注意,更改Git标签对包装的消费者有何影响


警告:使用git tag new old将会创建一个指向旧标签的标签,而不是旧标签的提交。(请参阅为什么我不能从Git GUI签出我的标签?
Stevoisiak,

1
@StevenVascellaro感谢您的链接。下一次,请进行编辑 -回答也是社区的努力。谢谢。
kaiser

我没有进行编辑,因为我还没有为自己测试过代码。(请注意相关问题的提交日期)
Stevoisiak

一旦完成git tag new old^{},就不需要了git tag new_tag_name old_tag_name(第一步)。
Number945 '18

28

如果已发布,则不能将其删除(也就是说,不必冒被涂焦油和羽毛的危险)。“ Git方式”是:

理智的事情。只要承认您搞砸了,并使用其他名称即可。其他人已经看到一个标记名,如果您使用相同的名称,则可能是两个人都有“ X版本”,但实际上却有不同的“ X”。因此,只需将其称为“ X.1”即可完成。

或者,

疯了 您真的也想将新版本称为“ X”,即使其他人已经看到了旧版本。因此,只需再次使用git-tag -f,就好像您尚未发布旧版本一样。

太疯狂了,因为:

Git不会(也不应该)更改用户背后的标签。因此,如果有人已经获得了旧标记,那么在您的树上执行git-pull不仅应该使他们覆盖旧标记。

如果有人从您那里获得了发行标签,则您不能仅仅通过更新自己的标签来为其更改标签。这是一个很大的安全问题,因为人们必须能够信任他们的标记名。如果您真的想做疯狂的事情,则需要认真地做,然后告诉别人您搞砸了。

所有礼貌的手册页


6
或者,您可以标记(使用正确的名称)此错误命名的标记。
2009年

6
谢谢,我已经浏览过该手册页一百万次。幸运的是,不良标签尚未在任何地方发布。即使是这样,这也是一个内部项目,并且我是目前唯一的开发人员。我认为我的皮毛和羽毛都很安全,但前提是我可以得到与文档相匹配的仓库。
布兰登·福斯迪克2009年

有时,我会将标记用作自己的个人参考。例如。可能是“ ok_jb”标签。我之所以使用它,是因为与我一起工作的某些人无法针对我的平台进行构建,因此有时会出现构建错误。然后,通过签出该标签,我可以快速获得构建的版本。构建新源时,我只需移动标签,或者将其重命名为builds ##,其中##是数字(取决于项目)。我还可以通过添加标签来强调引入特殊功能的时间。

7
可怜的答案。“不做”永远不是“我该怎么做?”的正确答案。用户并不是在问您是否认为这样做是个好主意,还是人们会喜欢这样做。如果有人问“我该如何切断我的手”,要么告诉他如何做,要么让他独自一人,但他不需要别人告诉他割手可能不是一个好主意。而且您可以做到。从技术上讲,即使在远程存储库中,您也可以添加新标签并删除旧标签。
梅基2015年

5
这似乎回答了以下问题:“如何使现有标签指向其他修订版?” 而不是OP的问题:“如何重命名标签?” 还不清楚如何告诉别人您搞砸了将如何解决问题(即使通常这是一个好主意)。
LarsH

25

这个Wiki页面具有这个有趣的单行代码,它提醒我们可以推送多个参考

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>对于<old-tag>:引用的每个提交<refs/tags/old-tag>:<refs/tags/new-tag>
  • 删除<old-tag>:<refs/tags/old-tag>

参见示例“ 在git存储库中更改标签的命名约定? ”。


这会保留注释吗?
Brandon Fosdick 2014年

1
请注意,这会将原始标签名称留在带注释标签的注释中!!我不确定这是否实际上意味着什么,至少在当前版本中。
gbr

@gbr您可以使用显示注释中剩余“原始标签名称”的示例来编辑答案吗?
VonC

1
@VonC我不确定我是否理解您的要求;也许我不太清楚:注解对象包含一个设置为标签名称的标签字段,您可以通过git cat-file -p <tag>; 看到它。在我的系统上使用您的方法时,我确实获得了“重命名”标签ref(<new-tag>),但其标签字段仍为<old-tag>
gbr 2015年

3
@gbr不是OP想要的吗?他提到“我应​​该指出的是,我还希望这个神奇的标签重命名过程能够保留正在重命名的标签中的注释。实际上,我真的很想更改名称,而无需更改其他任何东西”(stackoverflow.com/questions/1028649/您如何重命名一个git-tag /…
VonC

25

作为其他答案的补充,我添加了一个别名以一步完成所有操作,并具有更熟悉的* 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

这对我不起作用,因为它失败了!sh(有关Windows Git的问题),但是,将格式更新为以下格式后,它起作用了:renametag = "!f() { git tag $2 $1; git tag -d $1; git push origin :refs/tags/$1; git push --tags; }; f"
Sunny Patel

10

对于一个或几个标签,请遵循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做好了标记名称更改的准备,就可以将这些更改推回原点,以供其他人使用。


它缺少推回已删除标签的步骤:git push origin :refs/tags/v0.1.0-Demo和推回标签(以及其他未决事项)的步骤git push --tags
Star Wolf

6

对于喜欢冒险的人,可以通过以下命令完成:

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

7
如果裁判装满了git gc
行李箱

2
这也只会影响本地回购。如果您配置了远程服务器,我不确定这会导致什么负面影响。我不推荐这种方法。
therealklanni

1
还要注意,对于带注释的标签,这可能会更加麻烦,因为“注释” blob包含标签的原始名称。实际上,我不确定是否有任何东西使用它(希望至少是通过verify-tag使用),但是我不会冒险。
gbr

1
@gbr可以正常工作。(当然,要考虑@forivall的注释。)这个技巧在ALT Sisyphus构建系统中已被广泛使用。查看如何存储包的源,例如:git.altlinux.org/gears/g/gear.git。诸如2.0.7-alt1之类的可读标签是维护者提交给构建系统的签名标签。构建系统将隐含标签gb-sisyphus-task164472.200放在此处,以跟踪已从该源构建并发布了pkg的任务ID。它们是哑本(cp),维护者的信息保持不变。
imz –伊万·扎哈拉里舍夫(Ivan Zakharyaschev)

@ imz--IvanZakharyaschev很高兴知道,尽管将来它不会在某些产品上引起问题,但我不会太信任它。git存储库格式和预期的交互没有真正的规范,因此,在可行的情况下,我将努力以最令人惊讶的方式进行
整洁的工作

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中所述),我个人建议首先在服务器上复制新标签,然后删除旧标签。这样,在删除旧标签时,新标签不会被随机删除,并且标签的同步想要删除服务器上尚未存在的新标签。因此,例如,我们在一起得到:

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

3

您还可以通过单个git push命令将旧标签/分支复制到新名称并删除旧名称,而无需检出远程标签来重命名。

远程标签重命名/远程分支→标签转换:(注意::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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.