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

yuvru6vn  于 2023-06-28  发布在  Git
关注(0)|答案(3)|浏览(150)

长话短说,我正在写一个脚本,将一个非常大的项目从(喘气)Microsoft SourceSafe迁移到Git,我试图保留SourceSafe项目标签(本质上是Git中的标签)的作者。我知道你可以修改Git Commit的作者和提交者的名字/日期,但是你能对Git Tag做同样的事情吗?

hfyxw5xn

hfyxw5xn1#

TL;DR

使用新的所需数据重新创建标记。但是如果其他人以前有过他们,他们可能不会接受你的新的。或者他们可以!但这取决于他们。

说明

我知道你可以修改Git提交的作者和提交者的名字/日期
事实上,你不能,事实上,你不能(以及你能做什么)在答案的其余部分起着重要的作用。
所有的Git对象都有一个哈希ID作为它们的“真实名称”。通过计算对象内容的加密校验和来形成散列。这意味着你永远不能改变任何Git对象。1你 * 能 * 做的是构造一个 * 新 * 对象,然后说服所有拥有旧对象的人停止使用它,并使用新对象。
这就是git commit --amend所做的(以及各种交互式变基选项(如editreword)也可以做的)。首先我们将原始的Git对象提取为普通数据,在这里我们可以操作它;然后我们进行操作并要求Git构造一个新对象;最后,我们停止使用旧对象,并开始使用新对象。
对于 tip commit(参见gitglossary中 head 的定义)的提交,只要我们还没有推送那个提交,这一切都进行得非常简单和顺利。没有额外的提交引用回这个提示提交,所以我们做了一个“同样好”的新提交,将分支名称(head)重定向到新提交,并忘记我们刚刚替换的原始提交。它看起来像是我们改变了一个提交,但我们得到了一个新的哈希ID。

如何应用于标签

Git有两种标签,一个是 *lightweight标签 *,另一个是 *annotated标签 *。它们之间的区别在于,带注解的标记由指向 * 标记对象 * 的轻量级标记组成。它是具有标记器信息的标记对象。(轻量级标记本身没有这样的信息,它只是直接指向commit对象。
因此,要“改变”一个标记对象,我们必须做与“改变”一个提交对象相同的事情:将其复制到一个 new 标记对象。
没有内置的命令来完成这项工作,但是很容易用git cat-file -pgit mktag构建一个,git cat-file -p允许您将原始标记提取为普通数据,git mktag允许您将普通数据转换为新的标记对象。例如,Git存储库中的v2.2.1标签以以下开头:

$ git cat-file -p v2.2.1
object 9b7cbb315923e61bb0c4297c701089f30e116750
type commit
tag v2.2.1
tagger Junio C Hamano <...

object行是标记指向的提交:

$ git cat-file -t 9b7cbb315923e61bb0c4297c701089f30e116750
commit

所以我们可以将这个标签复制到一个新的带有不同tagger的标签:

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

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

标签支持PGP签名

上面的标签接着说:

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

里面有PGP签名此签名涵盖除签名本身之外的所有数据。如果您复制并修改此标记,则应完全丢弃原始签名(它将无效,并且将无法通过任何应用的测试);您是否可以并且应该用新的签名替换它,如果可以,由您决定谁的签名。

标签不能改变目标对象

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

$ git rev-parse v2.2.1
7c56b20857837de401f79db236651a1bd886fbbb

这是我们到目前为止看到的数据。

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

然而,标签通常是“众所周知的”。事实上,标记的意义--特别是PGP签名的带注解标记,PGP签名让您验证没有人篡改标记数据--是为了 * 保证 * 您可以确信这个标记是 * 正确的 * 标记,并且它指向的提交对象是原始提交而不是特洛伊木马。如果你改变了一个现有的标签,你就破坏了这个意图。此外,一些知道前一个标记值的人会拒绝接受新值:你将无法让他们更新现有的标签。只要你在别人拿到标签之前就这么做,他们永远不会知道,你会没事的。
1或者更确切地说,您无法更改Git对象的内容,除非您可以break the hash。参见How does the newly found sha1 collision affect git?

ohtdti5x

ohtdti5x2#

不像提交,你可以很容易地从远程删除标签,用你想要的作者名重新创建它们。

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>
k4aesqcs

k4aesqcs3#

一个额外的细节:在创建带注解/签名的标签时,git tag将使用GIT_COMMITTER_NAMEGIT_COMMITTER_EMAILnotGIT_AUTHOR_NAME/GIT_AUTHOR_EMAIL)作为“Tagger”字段。
创建一个不同名称/email的标签,而不改变全局Git配置

GIT_COMMITTER_NAME="name" GIT_COMMITTER_EMAIL="email" git tag -am"1.0.0" v1.0.0 <commit>

注1:要创建签名标记(-s),需要指定身份的私钥(这是签名的要点)。
注2:也可以重新创建具有特定时间戳的旧标签。例如:GIT_COMMITTER_DATE="Wed Dec 16 22:33:44 UTC 2020" ...

相关问题