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

jar*_*red 205 git git-tag

我们的git存储库中有几个带注释的标签.较旧的标签有伪造的消息,我们想要更新为我们的新风格.

% git tag -n1
v1.0 message
v1.1 message
v1.2 message
v2.0 Version 2.0 built on 15 October 2011.
Run Code Online (Sandbox Code Playgroud)

在此示例中,我们希望使v1.x消息看起来像v2.0消息.有谁知道我们会怎么做?

And*_*ndy 239

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

这将创建一个具有相同名称的新标记(通过覆盖原始标记).

  • 回答我自己的评论问题:是的,它_does_更改日期.:( (13认同)
  • 请参阅`git tag --help`中的"On Backdating Tags"部分. (9认同)
  • 这是否保持原始标签的日期? (6认同)
  • 还应该注意的是,您还可以附加多条消息(它们由新行分隔 - 在GitHub上)`git tag <tag name> <tag name> -f -m"<new message>" - m"<new消息>" - m"<新消息>"` (6认同)
  • @ChrisMorley在http://stackoverflow.com/a/23532519/603949下面查看我的答案 - 简而言之,当你想要替换`old tag`时,请使用`<tag name> ^ {}` (5认同)
  • 为了保留原始日期,基于@dahlbyk观察:`git checkout SHA1_OF_COMMIT``GIT_COMMITTER_DATE ="$(git show --format =%aD | head -1)"git tag TAG_MODIFIED TAG_MODIFIED -f -m"标签的新消息"` (3认同)
  • **警告**:这会创建一个指向您的旧标签的重复标签。请参阅 [Sungam 的回答](/sf/answers/1647276361/)以获得更安全的解决方案。 (2认同)
  • `&lt;tag name&gt;^{}` 的东西对我不起作用。经过一番搜索后,我确定[这是 Windows 的东西](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects): `cmd.exe` 使用 `^` 作为shell 逃逸,所以你需要将其加倍。 (2认同)

Eri*_* Hu 82

要更新复杂消息,只需使用带-a符号标记选项或带签名标记选项-s:

git tag <tag name> <tag name>^{} -f -a
Run Code Online (Sandbox Code Playgroud)

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

  • `&lt;tag name&gt;^{}` 的东西对我不起作用。经过一番搜索后,我确定[这是 Windows 的东西](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects): `cmd.exe` 使用 `^` 作为shell 逃逸,所以你需要将其加倍。 (3认同)
  • 请注意,John Kugelman编辑的`^{}`的想法基本上来自[Sungam的回答](/sf/answers/1647276361/)。 (2认同)

Sun*_*gam 37

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

这是对AndyEric Hu的回答的改进.他们的答案将创建一个引用旧标记对象的新标记对象,其中两个标记对象将具有相同的标记名称.

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

  • @BrentFoust,仅当你的头部位于标记的commit`use:git标签[-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>时才有效] <tagname> [<head>]` (4认同)
  • `&lt;tag name&gt;^{}` 的东西对我不起作用。经过一番搜索后,我确定[这是 Windows 的东西](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects): `cmd.exe` 使用 `^` 作为shell 逃逸,所以你需要将其加倍。 (2认同)

sta*_*anm 31

TL; DR

您可以通过删除标记并在欺骗日期和作者的同时重新创建它来执行此操作:

> git tag -d <tag-name>
> [GIT_COMMITTER_DATE=<original-commit-date>] \
> [GIT_AUTHOR_NAME=<original-author-name>] \
> git tag <tag-name> [commit]
Run Code Online (Sandbox Code Playgroud)

整个故事:

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]
Run Code Online (Sandbox Code Playgroud)

2. Sungram的进步

使用将<tag name>^{}作为git tagwill 的第二个参数,而不是删除所有以前具有相同名称的标记.

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

> 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]
Run Code Online (Sandbox Code Playgroud)

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]
Run Code Online (Sandbox Code Playgroud)

参考文献:

4. DIY

或者更新标签,您可以删除它们并再次创建它们.事实证明,更新只会添加一个新标记并使其指向旧标记,或者只是隐式删除旧标记并创建一个新标记以指向同一个提交.

你可以通过发布:

> git tag -d <tag-name>
> [GIT_COMMITTER_DATE=<original-commit-date>] \
> [GIT_AUTHOR_NAME=<original-author-name>] \
> git tag <tag-name> [commit]
Run Code Online (Sandbox Code Playgroud)

[optional]是一个可选字段; <required>是必填字段.当然,您可以在git tag通常的命令之后添加任何标志.

  • 感谢您指出"他们的答案将创建一个新的标签对象"! (3认同)

liu*_*ng1 10

@Andy的解决方案

git tag <tag-name> <tag-name> -f -a
Run Code Online (Sandbox Code Playgroud)

错的.在它之后,用

git show
Run Code Online (Sandbox Code Playgroud)

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

它在commit时添加一个具有相同标记名称和新消息的新标记<tag-name>.但它不会删除旧标签.这是该命令的一个特例:

git tag [<commit> | <old-tag>] <tag-name>
Run Code Online (Sandbox Code Playgroud)

<old-tag>就是一样<tag-name>.


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

git tag <tag-name> -f -a
Run Code Online (Sandbox Code Playgroud)

记住, 这里只有一个.

如果我们想要改变标签,那么HEAD我们需要一个额外的<commit>参数.

git tag <commit> <tag-name> -f -a
Run Code Online (Sandbox Code Playgroud)

  • 请注意,自您回答以来,安迪的解决方案已更新。也许最好以一条消息来开始你的回答,说它已经被修复了?也可能是你的命令 `git tag &lt;commit&gt; &lt;tag-name&gt; -f -a` 的 &lt;commit&gt; 和 &lt;tag-name&gt; 颠倒了?与其他答案和文档进行比较时,它看起来是这样的,但我不是专家。 (2认同)

man*_*lds 6

您必须使用-f强制标志再次标记。

git tag v1.0 -f -m "actual message"
Run Code Online (Sandbox Code Playgroud)

  • 该解决方案假设当前的 git head 版本为 1.0。如果不是的话,这可能会把事情搞砸,因为它更改了与版本 1.0 相关的修订版。安迪的解决方案避免了这个陷阱。 (4认同)

Von*_*onC 6

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

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

参见Nicolas Morey-Chaisemartin()的commit 9eed6e4(2018年2月6日(通过合并JUNIOÇ滨野- -提交05d290e,2018年3月6日)nmorey
gitster

tag:添加--edit选项

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

  • 您能用`--edit`提供一个连贯的例子来解决OP吗? (2认同)
  • @JoshHabdas 实际上,您需要添加 -f 选项:--edit 仅允许进一步编辑消息。 (2认同)

h0t*_*1r3 5

使用上面的答案(尤其是Sungam 的),这是我的别名 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 '"
Run Code Online (Sandbox Code Playgroud)

改进?

  • 还保留作者: `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 '"` (2认同)
  • 刚刚尝试过这个。它没有为替换标签提供标签本身的作者和日期信息,而是使用标签指向的提交中的信息。这不一定是相同的,事实上,大多数时候对于我们的情况来说是不一样的。我们拥有多存储库基础设施,并在“核心”存储库中使用带注释的标签来记录有关跨多个存储库的推送的信息。因此,在核心中,所指向的提交甚至可能不是真正推送的一部分。带注释的标签中的信息应反映其他存储库中的真实推送。 (2认同)