如何在 Git 中重命名带注释的标签

How to rename an annotated tag in Git

如何在 Git 中重命名现有的注释标签?

我在存储库上有将近一百个代表版本号的标签,每个标签都附有关于该版本更改内容的有用描述。我想改变我用于这些标签的命名风格,记录标签消息,删除标签,并用旧消息和新名称重新创建它对于将近一百个标签手动完成将是一场噩梦.执行此操作的脚本或一系列 git 命令对于自动化很有用。

坏消息是带注释的标记对象的名称嵌入在该带注释的标记对象中。所以如果你想完全彻底,你需要替换那些标签对象:

  • 如果它们是签名的标签,您将需要使用新签名重新生成它们。

  • 否则,可以将标签对象复制到新的标签对象,并进行系统名称更改。例如,filter-branch 命令就是这样做的。 (这有点难看,因为您必须使用一些低级管道命令;没有简单方便的方法。但请参阅下文。)

好消息是,没有绝对要求您将 "correct" 带注释的标签与轻量级标签一起使用。也就是说,带注释的标签实际上是一对实体:一个轻量级标签(带有一些名称,只是 refs/tags/ name-space 中的一个条目),以及带注释的标签对象(在存储库中本身)通常在其 tag 字段中具有相同的名称。但是你可以创建一个新的轻量级标签指向现有的带注释的标签对象,然后选择性地删除原来的轻量级标签:

$ git cat-file -p v2.5.0 | sed 's/@/ /'
object a17c56c056d5fea0843b429132904c429a900229
type commit
tag v2.5.0
tagger Junio C Hamano <gitster pobox.com> 1438025401 -0700

Git 2.5
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAABAgAGBQJVtoa5AAoJELC16IaWr+bLRtQP/0RYjVe9fLubiN5vLaAJ98B5
K3apw8bScJ4bZQJiOGMZg7AJ8pSB9XchqopjNlO2v8XVrZEkFPQ7ln3ELjOITusO
0MIZz6Y4sS0yqMklNPWx/OIzvSyKOs8quUA/J87Ha+pnMYlobDgWJxDnZ3hVO6q2
0lVMRUvwM9qsBiPsVKyAba5qPDBn9uTjgR/hivA3Ha97foq/qMM6rjERp5hX8KTE
JacLMlx7ZSAJiNKmz1mVk+xyDVGDh9nojiz93jRYohAM8gsbyyRayPGKlKsMrajC
s0bLxilV8zupNrMOs54ND71VqNo992ewiCrB3FBpTah2rPE0MKsxCY72pFiZp/hn
w1I3seQbd880d2TXfczVVphG3xN3xbfnC+aEqobgPuFIgGxHqeWqUpDQnWa0XhtK
i5phhENEjbMdCDGf7ylRRvCTL5O2Mz1XnNfZBP0uqIX6PyzaCwcZM1DUP0xY8Nvz
xo0BplMvK4sAr+fCW0HHHlDO6Ky3jjRyPUEyVEbwF50lZ3Sgzkkf32I06yeZgQW9
Ge6+qGopw7JVQM95UDMBysbQSNuTmwnclwn0DBfc85vQwZw5OwnRk0RsQxcnqNr2
B4Nyubl8Pge4H0T0pahpAdr0AU7JHv4i4yYZh1Dr4d+hzzXAK+ospCxkcJVX7Qz5
BP8pbLPj3ubLAenxg71I
=xfTv
-----END PGP SIGNATURE-----
$ git rev-parse v2.5.0
8d1720157c660d9e0f96d2c5178db3bc8c950436
$ git tag silly v2.5.0
$ git rev-parse silly
8d1720157c660d9e0f96d2c5178db3bc8c950436
$ git tag -d v2.5.0
Deleted tag 'v2.5.0' (was 8d17201)
$ git for-each-ref refs/tags/silly
8d1720157c660d9e0f96d2c5178db3bc8c950436 tag    refs/tags/silly

(我恢复了旧标签并在此之后删除了 "silly" 版本,所以它没有经过彻底测试,但至少没有爆炸。)

要自动复制标签或重新创建标签(带或不带签名),只需使用 git for-each-ref to find all the old tags, and use the resulting names to make the new tags. Use git cat-file -p to pretty-print the existing tag for modifying to make the new tag, or simply make the new tag pointing to the existing tag object. After printing the tag (to a pipe or file) you can edit it with sed or some other programmable editor, and feed the result to git tag -F as an input file, or to git mktag 创建标签对象,将生成的 SHA-1 提供给 git tag制作相应的轻量级标签。

(注意:如果您已经通过编写 bash 脚本来完成所有这些,并且只需要帮助来完成它或更正其中的一些问题,post 到目前为止的脚本。)

总结 您想要将单个带注释的标签 v1.0.0 重命名为仅 1.0.0

的情况

变体 1:重命名 替换两者,轻量级标签 底层标签对象

警告:

  • 会破坏签名标签的签名。仅用于未签名的注释标签。
  • 像下面这样的天真 sed 替换也会 更改标记消息和标记的标记器名称 (如果有)中 v1.0.0 的出现。如果这不是您想要的,请使用更具体的 RegEx。
git tag "1.0.0" $(git cat-file -p "v1.0.0" | sed 's/v1\.0\.0/1.0.0/g' | git mktag)
# You might want to check the result before continuing to delete the old tag.

# Delete the old tag locally
git tag -d v1.0.0

# Delete the old tag on the default remote (origin)
git push origin :v1.0.0

变体 2:重命名仅替换轻量级标签并使其指向原始基础标签对象

git tag "1.0.0" "v1.0.0"

# Delete the old tag locally
git tag -d v1.0.0

# Delete the old tag on the default remote (origin)
git push origin :v1.0.0