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

我们的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消息。我们该怎么做呢?

108766 次浏览
git tag <tag name> <tag name>^{} -f -m "<new message>"

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

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

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

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

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

这将打开一个编辑器使用旧标记消息的内容

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

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

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

博士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. 接受的答案

这是对安迪埃里克·胡的答案的改进。 他们的答案将创建一个引用旧标记对象的新标记对象,并且两者具有相同的名称。< / p >

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

> 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命令后面添加任何标志,就像你通常会做的那样

使用上面的答案(特别是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年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

记住,这里只有一个

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

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

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

在Git 2.17(2018年第二季度)中,将有一种使用git tag <tag name> <tag name> -f -m "<new message>"创建标记的替代方法,因为"git tag"学习了一个明确“--edit"选项,它允许通过“;-m"和“;-F"有待进一步编辑。

参见提交9 eed6e4 (06 Feb 2018) by 尼古拉斯·莫雷-查斯马丁(nmorey)
(由Junio C Hamano—gitster提交05 d290e中合并,06 Mar 2018)

tag:添加--edit选项

添加一个--edit选项,允许修改由-m-F提供的消息,与git commit --edit的方式相同。

如果你使用的是像smartgit这样的GUI

  1. 在新消息的相同位置再次创建相同的标记
  2. 选择“覆盖现有标签”
  3. 强制将标记推送到上游存储库

下面是一组别名,它应该基于这里现有的答案(特别是stanm的)为你做这件事:

# Edit an existing tag, preserving the date and tagger
tag-amend = "!f() { : git tag ;\
eval \"`git x-tag-environment-string`\";\
git tag -a -f --edit -m \"$(git x-tag-message \"$1\")\" \"$1\" \"$1^{}\" \"${@:2}\";\
}; f"


# Rewrite an existing tag, preserving the date and tagger (accepts -m and -F)
tag-rewrite = "!f() { : git tag ;\
eval \"`git x-tag-environment-string`\";\
git tag -a -f \"$1\" \"$1^{}\" \"${@:2}\";\
}; f"


# Helpers to Extract the Tag Data
x-tag-data = tag -l --format
x-tag-message = x-tag-data '%(contents)'
x-tagger-name = x-tag-data '%(taggername)'
x-tagger-email = x-tag-data '%(taggeremail)'
x-tag-date = x-tag-data '%(taggerdate:rfc2822)'
x-tag-environment-string = "!f() { echo '\
export GIT_COMMITTER_DATE=${GIT_COMMITTER_DATE-`git x-tag-date \"$1\"`};\
export GIT_COMMITTER_NAME=${GIT_COMMITTER_NAME-`git x-tagger-name \"$1\"`};\
export GIT_COMMITTER_EMAIL=${GIT_COMMITTER_EMAIL-`git x-tagger-email \"$1\"`};\
';}; f"

这些别名接受单个标记名和git标记的任何其他标记,并且可以很容易地进行修改以支持名称更改。

用法:

# opens editor to edit existing message
git tag-amend <tag name>


# add a new paragraph to the existing message
git tag-amend <tag name> -m "<new paragraph>"


# replace the message with a new one
git tag-rewrite <tag name> -m "<new message>"

支持轻量级标签

使用creatordatecreatorname,和creatoremail代替tagger...变量。creator...快捷方式将使用tagger...(如果存在的话)并回退到committer...