如何在Git中重命名一个已注释的标签

12

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

我有将近一百个代表版本号的标签,并且每个标签都带有有用的描述,说明了该版本所改变的内容。我想要更改这些标签的命名方式,但手动按照旧名称记录标签信息、删除标签,再创建新标签并给其赋上旧的信息和新名称,对于将近一百个标签来说会非常麻烦。编写一个脚本或者一系列 Git 命令可以用于自动化操作。

2个回答

10
坏消息是,一个带注释的标签对象的名称被嵌入到该带注释的标签对象中。因此,如果你想彻底地做好,你需要替换这些标签对象:
- 如果它们是签名标签,你需要用新签名重新生成它们。 - 否则,可以将标签对象复制到新的标签对象中,并进行系统性的名称更改。例如,`filter-branch` 命令就可以做到这一点。(这有点丑陋,因为你需要使用一些低级的管道命令;没有简单方便的方法。但请参见下文。)
好消息是,并不绝对要求你使用“正确”的带注释标签和轻量级标签。也就是说,一个带注释的标签实际上是一对实体:一个轻量级标签(其名称只是 `refs/tags/` 命名空间中的一个条目),以及一个带注释的标签对象(在存储库本身中),它通常在其 `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

我恢复了旧标签并删除了“愚蠢”的版本,所以它没有经过彻底测试,但至少它没有出现故障。

要自动复制标签或重新创建标签(带有或不带有签名),只需使用git for-each-ref找到所有旧标签,并使用生成的名称创建新标签。使用git cat-file -p来漂亮打印现有标签以进行修改以创建新标签,或者直接创建指向现有标签对象的新标签。在将标签打印到管道或文件后,您可以使用sed或某些其他可编程编辑器对其进行编辑,并将结果提供给git tag -F作为输入文件,或者提供给git mktag创建标签对象,将生成的SHA-1提供给git tag以生成相应的轻量级标签。

(注意:如果您已经开始编写bash脚本来完成所有这些操作,只需寻求帮助以完成或纠正其中的某些问题,请发布部分脚本。)


我还没有尝试过,但是你的方法看起来比脚本更快速地设置。如果我认为它对某人有用,我会发布我制作的脚本,该脚本只从 git tag -n99 中提取有用信息,否则感谢你提供的 Git 方法 =) - Parker Hoyes

9

总结torek的答案,当您想要将单个注释标记v1.0.0重命名为1.0.0时:

变体1:重命名替换轻量级标记及其基础标记对象

警告:

  • 这将破坏签名已签署标记。 只能用于未签署的注释标记。
  • 像下面这样的天真的sed替换也会更改标记消息中的v1.0.0以及标记的标记者名称(如果有)等出现次数。 如果这不是您的意图,请使用更具体的正则表达式。
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

方案二:仅替换轻量级标记,并使其指向原始的基础标记对象

该方案涉及IT技术相关内容。
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

1
或者你可以不在sed命令中添加"g"标记;这样只有第一个匹配项(即标签名称)会被更改。 - Paul Du Bois
1
或者只需匹配行的确切格式s/^tag v1\.0\.0$/tag 1.0.0/ - Cheetah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接