如何在git中编辑现有标签消息?


225

我们的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消息。有人知道我们将如何做吗?


2
注意:使用Git 2.17(2018年第二季度),简单git tag -m "A message" --edit v1.0就足够了。请参阅下面的答案
VonC


@VonC尝试过并fatal: tag 'v6.6.2' already exists使用接收2.17.0
Josh Habdas '18

1
您始终可以删除先前的标签,然后再次进行。
RoadRunner '18

Answers:


264

git tag <tag name> <tag name>^{} -f -m "<new message>"

这将创建一个具有相同名称的新标签(覆盖原始标签)。


7
这会保持原始标签的日期吗?
James M. Greene

16
回答我自己的评论问题:是的,它的确更改了日期。:(
詹姆斯M.格林,

10
请参阅中的“在回溯标签上”部分git tag --help
dahlbyk

6
还应当指出的是,你还可以追加多个消息(他们得到一个新行分离-在GitHub上)git tag <tag name> <tag name> -f -m "<new message>" -m "<new message>" -m "<new message>"
布莱尔麦克米兰

5
@ChrisMorley在stackoverflow.com/a/23532519/603949下查看我的回答-简而言之,<tag name>^{}当您要替换old tag
Sungam时,将于2014年

87

要更新复杂的消息,只需将带注释的标签选项指定为-a或将带标记的标签选项指定为-s

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

这将打开一个带有旧标签消息内容的编辑器。


39

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

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

<tag name>^{} 将解析标签/引用,直到找到第一个提交哈希。


4
@BrentFoust,仅当您的头部处于标记的提交 usage: git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]
时才有效

33

TL; DR

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

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

整个故事:

基于Sungram的答案(最初建议作为编辑):

1.接受的答案

这是对AndyEric 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的进步

使用<tag name>^{}作为第二个参数git tag具有相同的名称将改为删除所有以前的标签。

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

> 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]

参考文献:

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 tag通常的命令后添加任何标志。


3
感谢您指出“他们的答案将创建一个新的标记对象”!
cwhsu

引用安德烈亚斯·施瓦布(Andreas Schwab)The tagger is controlled by the committer info. (...) GIT_COMMITTER_{NAME,EMAIL}. A tagger isn't really an author.
伊万·武恰卡(IvanVučica)

11

@Andy的解决方案

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

错误的。之后,用

git show

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

它将在提交时添加具有相同标签名称的新标签和新消息<tag-name>。但是,它不会删除旧标签。这是此命令的特例:

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

<old-tag>与一样<tag-name>


正确的解决方法很简单,只需更新标签即可。

git tag <tag-name> -f -a

记住, 这里只有一个

如果我们想要更改标记(不是)HEAD,则需要一个额外的<commit>参数。

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

是!你是对的。感谢您指出这一点。重写标签几次后,我检查了标签,git show <tag>看到了所有以前的版本。
Manoel Vilela

问题是:如果我需要更新不是的某些标签,则HEAD传递多余<commit>的标签,打开的标签为空。我希望旧标签可以编辑。有办法吗
Manoel Vilela

请注意,自您回答以来,安迪的解决方案已更新。也许最好先以一条已被修复的消息开始您的答案?也可能是您的命令git tag <commit> <tag-name> -f -a颠倒了<commit>和<tag-name>吗?与其他答案和文档进行比较时,它看起来是这样,但我不是专家。
Jacob Akkerboom

7

我们希望使v1.x消息看起来像v2.0消息

在Git 2.17(2018年第二季度)中,将可以使用创建标签的替代方法git tag <tag name> <tag name> -f -m "<new message>",因为“ git tag”了解了一个明确的“ --edit”选项,该选项允许进一步编辑通过“ -m”和“ -F” 给出的消息。

参见提交9eed6e4(2018年2月6日) Nicolas Morey-Chaisemartin(nmorey)的)
(由Junio C gitsterHamano合并--commit 05d290e,2018年3月6日)

tag:添加--edit选项

添加一个--edit选项,该选项允许以相同的方式修改-m或提供的消息。-Fgit commit --edit


4
您能否提供一个使用--edit该OP 的连贯示例?
乔什·哈布达斯

@JoshHabdas实际上,您需要添加-f选项:--edit仅允许对消息进行进一步编辑。
VonC

谢谢。因此,如果-f还添加--edit了标记,则将编辑消息并修改时间戳,对吗?
乔什·哈布达斯

@JoshHabdas这是个主意,是的。
VonC

4

您将不得不使用-fforce标志再次进行标记。

git tag v1.0 -f -m "actual message"

3
该解决方案假定当前的git head版本为1.0。如果不是这样,可能会搞乱事情,因为它会更改与版本1.0相关的修订。安迪的解决方案避免了这种陷阱。
埃里克·O·勒比戈特

4

使用上面的答案,这是我的别名one-liner .gitconfig。替换现有标签并保留提交日期。

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

有改善吗?


1
也保持作者: tag-amend = "!sh -c 'f() { name=$(git log -1 --format=%an $0); email=$(git log -1 --format=%ae $0); date=$(git log -1 --format=%ci $0); GIT_AUTHOR_NAME=\"${name}\" GIT_COMMITTER _NAME=\"${name}\" GIT_AUTHOR_EMAIL=\"${email}\" GIT_COMMITTER_EMAIL=\"${email}\" GIT_AUTHOR_DATE=\"${date}\" GIT_COMMITTER_DATE=\"${date}\" git tag -f -a $0 $0^{}; }; f '"
最低

1
刚试过这个。它不使用标签本身为替换标签提供作者和日期信息,而是使用标签指向的提交信息。这不一定是相同的,实际上,在大多数情况下,对于我们的情况而言是不相同的。我们拥有多仓库基础架构,并在“核心”仓库中使用带注释的标签来记录有关跨越多个仓库的推送的信息。因此,从根本上讲,指向的提交甚至可能不是真正推动的一部分。带注释的标签中的信息应反映其他存储库中的实际推送。
tanager '18

0

如果您使用的是像smartgit这样的GUI ,

  1. 在新消息的相同位置再次创建相同的标签
  2. 选择“覆盖现有标签”
  3. 强制将标签推入上游存储库
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.