作者:阿思翠 | 来源:互联网 | 2023-01-31 22:09
长话短说,我正在编写一个脚本,将一个非常大的项目从(gasp)Microsoft SourceSafe迁移到Git,并且我试图保留SourceSafe项目标签的作者(这些标签实际上是Git中的标签)。我知道您可以修改Git提交的作者和提交者名称/日期,但是您可以对Git标签做同样的事情吗?
1> torek..:
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.1
Git的Git存储库中的标签开头为:
$ 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
这是到目前为止我们一直在查看的数据。
在新标签对象将有一些其他的,不同的哈希ID。当我们修改一个未发布的提交时,这没什么大不了的,因为没有其他人知道将某个分支名称映射到某个特定的哈希ID。
但是,标签通常是“众所周知的”。实际上,标签(尤其是PGP签名的带注释的标签,PGP签名使您可以验证没有人跟踪标签数据)的目的是确保您可以确保此标签是正确的标签,并且它指向的提交对象是原始提交,而不是某些特洛伊木马。如果更改现有标签,那么您正在颠覆此意图。此外,有些人谁知道前面的标签的值将简单地拒绝接受新的价值:你不会是能够让他们更新现有的标签。但是,只要您在其他人没有标签之前就这样做,他们将永远不会知道,您会很好的。
1或者,除非您可以破坏哈希值,否则您无法更改Git对象的内容。另请参阅新发现的sha1碰撞如何影响git?