我们的Git存储库中有几个带注释的标记。旧的标记具有虚假的消息,我们希望将其更新为新样式。

% git tag -n1
v1.0 message
v1.1 message
v1.2 message
v2.0 Version 2.0 built on 15 October 2011.

在这个例子中,我们想让v1。X消息看起来像v2.0消息。我们该怎么做呢?


当前回答

要更新一个复杂的消息,只需用-a指定带注释的标记选项或用-s指定带符号的标记选项:

git tag <tag name> <tag name>^{} -f -a

这将打开一个包含旧标记消息内容的编辑器。

其他回答

我们想要得到v1。X消息看起来像v2.0消息

在Git 2.17(2018年第二季度)中,将有一种替代方法来创建一个新的标记,使用Git标签<标签名> <标签名> -f -m" <新消息>",因为“Git标签”学习了一个显式的“——edit”选项,允许通过“-m”和“-f”给出的消息被进一步编辑。

参见Nicolas morey - chaisemmartin (nmorey)的commit 9eed6e4(2018年2月6日)。 (由Junio C Hamano - gitster -在commit 05d290e, 2018年3月6日合并)

标签:添加——编辑选项 添加一个——edit选项,允许修改-m或-F提供的消息,就像git commit——edit所做的一样。

Git标签<标签名> <标签名>^{}-f -a

这是一种改进:如果没有^{},它将创建一个引用旧标记对象的新标记对象,其中它们将具有相同的标记名称。

<标签名称>^{}将解析标签/引用,直到找到第一个提交散列。

使用上面的答案(特别是Sungam的答案),这是.gitconfig的别名一行程序。替换现有标签并保留提交日期。

[alias]
tm = "!sh -c 'f() { export GIT_COMMITTER_DATE=$(git log -1 --format=%ci $0); git tag -f -a $0 $0^{}; }; f '"

改进吗?

@安迪2016年的原始解决方案(最终更新)

git tag <tag-name> <tag-name> -f -a

是错误的。之后,用

git show

命令时,我们将看到具有相同名称的堆栈标记。

它在commit <tag-name>处添加了一个带有相同标签名的新标签和新消息。但它不删除旧标签。这是该命令的特殊情况:

git tag [<commit> | <old-tag>] <tag-name>

但是<old-tag>和<tag-name>是一样的。


正确的解决方法很简单,只要更新标签就可以了。

git tag <tag-name> -f -a

记住,这里只有一个。

如果我们想要change标签,而不是HEAD,我们需要一个额外的<commit>参数。

git tag <commit> <tag-name> -f -a

博士TL;

你可以通过删除你的标签并在欺骗日期和作者的同时重新创建它来做到这一点:

> git tag -d <tag-name>
> [GIT_COMMITTER_DATE=<original-commit-date>] \
> [GIT_AUTHOR_NAME=<original-author-name>] \
> git tag <tag-name> [commit]

整个故事:

基于Sungram的回答(最初是作为编辑提出的):

1. 接受的答案

这是对Andy和Eric Hu的回答的改进。 他们的答案将创建一个引用旧标记对象的新标记对象,并且两者具有相同的名称。

为了说明这一点,考虑以下情况:

> git tag tag1 tag1 -f -a  # accepted answer
> git rev-list --objects -g --no-walk --all
[ example output: ]
6bdcc347fca041a5138f89fdf5276b3ebf9095d5
260ab7928d986472895b8c55e54569b3f3cb9517 tag1
a5797673f610914a45ef7ac051e3ee831a6e7c25 tag1
f22d6308c3cd330a3b0d86b9bf05562faf6b6f17

> git show tag1
tag tag1
Tagger: [tagger]
Date:   [date of updated tag]
[Updated description]

tag tag1
Tagger: [tagger]
Date:   [date of original tag]
[Original description]

[tagged commit details]

2. Sungram的改进

使用<标签名>^{}作为git标签的第二个参数会删除之前所有同名的标签。

考虑上一个终端会话的延续:

> git tag tag1 tag1^{} -f -a  # suggested improvement
> git rev-list --objects -g --no-walk --all
[ example output: ]
6bdcc347fca041a5138f89fdf5276b3ebf9095d5
75f02acacfd7d91d55b5bcfdfb1f00aebeed15e3 tag1
f22d6308c3cd330a3b0d86b9bf05562faf6b6f17 

> git show tag1
tag tag1
Tagger: [tagger]
Date:   [date of updated tag]
[Updated description]

[tagged commit details]

3.保存日期

最后,如果您想保留原始标记的日期作为更新标记的日期,可以使用一些awk(或类似的)魔法,或者只是粘贴您想要的日期。下面是第二个例子的替代品(否则原始日期将由于覆盖而丢失):

> GIT_COMMITTER_DATE="$(git show tag1 |                              # get info about the tag cascade including the date original of the original tag
> awk '{
>     if ($1 == "Date:") {
>         print substr($0, index($0,$3))
>     }
> }' |                                                               # extract all the dates from the info
> tail -2 | head -1)"                                               `# get the second to last date, as the last one is the commit date` \
> git tag tag1 tag1^{} -a -f                                         # finally, update the tag message, but save the date of the old one
>
> git rev-list --objects -g --no-walk --all
6bdcc347fca041a5138f89fdf5276b3ebf9095d5
e18c178f2a548b37799b100ab90ca785af1fede0 tag1
f22d6308c3cd330a3b0d86b9bf05562faf6b6f17
> git show tag1
tag tag1
Tagger: [tagger]
Date:   [date of original tag]
[Updated description]

[tagged commit details]

引用:

SO:在git数据库中快速列出对象 SO:更改git标记的提交日期 Awk:教程和介绍 SO:通过第一个行符号过滤输出,并使用awk提取余下的行符号 SO:如何在多行命令中放入bash行注释

4. DIY

除了更新标记之外,您还可以删除它们并重新创建它们。事实证明,更新只是添加一个新标记,并使其指向旧标记,或者只是隐式地删除旧标记,并创建一个新标记,以指向相同的提交。

你可以通过发出以下命令来实现:

> git tag -d <tag-name>
> [GIT_COMMITTER_DATE=<original-commit-date>] \
> [GIT_AUTHOR_NAME=<original-author-name>] \
> git tag <tag-name> [commit]

这里[optional]是一个可选字段;<required>是必填字段。 当然,您也可以像往常一样在git标签命令后添加任何标志。