如何更改Git标签的Tagger名称和电子邮件

mol*_*297 4 git github visual-sourcesafe-2005 git-tag gitlab

长话短说,我正在编写一个脚本,将一个非常大的项目从(gasp)Microsoft SourceSafe迁移到Git,并且我试图保留SourceSafe项目标签的作者(这些标签实际上是Git中的标签)。我知道您可以修改Git提交的作者和提交者名称/日期,但是您可以对Git标签做同样的事情吗?

tor*_*rek 8

TL; DR

用新的所需数据重新创建标签。但是如果其他人以前有过,他们可能不会接受您的新朋友。否则他们可能会!不过,这取决于他们

描述

我知道您可以修改Git提交的作者和提交者名称/日期

实际上,您不能这样做,而您不能(以及可以做什么)这一事实在其余答案中起着重要作用。

所有Git对象都有一个哈希ID作为其“真实名称”。哈希是通过计算对象内容的加密校验和形成的。这意味着您根本无法更改任何Git对象。1可以做的是构造一个对象,然后说服拥有旧对象的每个人停止使用它,而改用新对象。

这是做什么的git commit --amend(以及各种交互式变基选项喜欢edit并且reword可以做的事情)。首先,我们将原始的Git对象提取到普通数据中,以便在其中进行操作;然后我们进行操作,并要求Git构造一个新对象;最后我们停止使用旧对象,而开始使用新对象。

对于属于尖端提交的提交(请参阅gitglossary中head的定义),只要我们还没有推送该提交,所有这些操作都非常容易且顺利进行。没有额外的提交引用此技巧提交,因此我们进行“同样好” 的新提交,将分支名称(head)重定向到新提交,而忘记我们刚刚替换的原始提交。它看起来像我们改变了提交,但我们得到了一个新的哈希ID代替。

这如何应用于标签

Git有两种标签,轻量级标签和带注释的标签。它们之间的区别在于,带注释的标签由指向标签对象的轻量级标签组成。具有标记信息的标记对象。(轻量级标签没有其自身的此类信息,它仅直接指向提交对象。)

因此,要“更改”标记对象,我们必须做与“更改”提交对象相同的操作:将其复制到新的标记对象。

没有内置命令可以执行此操作,但是很容易构建一个命令,git cat-file -p这可以使您将原始标签提取到普通数据中git mktag,而,您可以将普通数据转换为新标签对象。例如,v2.2.1Git的Git存储库中的标签开头为:

$ git cat-file -p v2.2.1
object 9b7cbb315923e61bb0c4297c701089f30e116750
type commit
tag v2.2.1
tagger Junio C Hamano <...
Run Code Online (Sandbox Code Playgroud)

object行是标记指向的提交:

$ git cat-file -t 9b7cbb315923e61bb0c4297c701089f30e116750
commit
Run Code Online (Sandbox Code Playgroud)

因此我们可以将此标签复制到另一个标签中tagger

$ new_hash_id=$(git cat-file -p v2.2.1 | sed -e .... | git mktag)
$ git update-ref refs/tags/$name $new_hash_id
Run Code Online (Sandbox Code Playgroud)

其中sed做任何必要的操作(请参见下文),并且$name是标签的名称。然后,我们将使轻量级标签v2.2.1指向中的新标签对象$new_hash_id。但是有两个问题(只有一个可能适用于您的情况)。

标签可能是PGP签名的

上面的标签继续说:

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
Run Code Online (Sandbox Code Playgroud)

然后有一个PGP签名。该签名涵盖签名本身以外的所有数据。如果您复制和修改此标签,则应完全放弃原始签名(该签名无效,并且将无法通过任何测试);是否可以并且应该将其替换为新签名,如果是,则由谁决定。

标签不应更改其目标对象

现有的轻量级标签v2.2.1当前指向现有的标签对象:

$ git rev-parse v2.2.1
7c56b20857837de401f79db236651a1bd886fbbb
Run Code Online (Sandbox Code Playgroud)

这是到目前为止我们一直在查看的数据。

标签对象将有一些其他的,不同的哈希ID。当我们修改一个未发布的提交时,这没什么大不了的,因为没有其他人知道将某个分支名称映射到某个特定的哈希ID。

但是,标签通常是“众所周知的”。实际上,标签(尤其是PGP签名的带注释的标签,PGP签名使您可以验证没有人跟踪标签数据)的目的是确保您可以确保此标签是正确的标签,并且它指向的提交对象是原始提交,而不是某些特洛伊木马。如果更改现有标签,那么您正在颠覆此意图。此外,有些人谁知道前面的标签的值将简单地拒绝接受新的价值:你不会是能够让他们更新现有的标签。但是,只要您其他人没有标签之前就这样做,他们将永远不会知道,您会很好的。


1或者,除非您可以破坏哈希值,否则您无法更改Git对象的内容。另请参阅新发现的sha1碰撞如何影响git?


小智 5

与提交不同,您可以轻松地从远程删除标签,并使用您想要的作者姓名重新创建它们

git tag -d <tag-name> 
git push origin :refs/tags/<tag-name>
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
git tag <tag-name> [commit]
git push origin <tag-name>
Run Code Online (Sandbox Code Playgroud)