Mercurial 全局变更集 ID 的分配
显然,Mercurial 为每个更改分配了一个全局更改集 ID。他们如何确保这是独一无二的?
Apparently Mercurial assigns a global changeset id to each change. How do they ensure that this is unique?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如 Zach 所说,变更集 ID 是使用 SHA-1 哈希函数 计算的。这是加密安全哈希函数的示例。加密哈希函数采用任意长度的输入字符串,并从此字符串生成固定长度的摘要。对于 SHA-1,输出长度固定为 160 位,默认情况下 Mercurial 仅显示前 48 位(12 个十六进制数字)。
加密哈希函数具有这样的特性,即很难找到产生相同输出的两个不同输入,即很难找到满足
H(x ) == H(y)
。这称为抗碰撞性。由于 Mercurial 使用 SHA-1 函数来计算变更集 ID,因此对于相同的输入(相同的更改、相同的提交者名称和日期),您会获得相同的变更集 ID。但是,如果您使用不同的输入 (
x != y
),则由于碰撞阻力,您将获得不同的输出(变更集 ID)。换句话说,如果您没有为不同的输入获得不同的变更集 ID,那么您就发现了 SHA-1 的冲突!到目前为止,还没有人发现 SHA-1 的碰撞,所以这将是一个重大发现。
更详细地说,SHA-1 哈希函数在 Mercurial 中以递归方式使用。每个变更集哈希值都是通过连接以下内容来计算的:
,然后对所有这些运行 SHA-1 (请参阅 changelog.py 和 revlog.py)。由于哈希函数是递归使用的,因此变更集哈希会将整个历史记录一直修复到变更集图中的根。
这也意味着,如果您使用相同的提交消息同时将行
Hello World!
添加到两个不同的项目中,则不会获得相同的变更集 ID - 当它们的历史记录不同时(不同的父变更集) ),两个新的变更集将获得不同的 ID。As Zach says, the changeset ID is computed using the SHA-1 hash function. This is an example of a cryptographically secure hash function. Cryptographic hash functions take an input string of arbitrary length and produces a fixed-length digest from this string. In the case of SHA-1, the output length is fixed to 160 bit, of which Mercurial by default only shows you the first 48 bit (12 hexadecimal digits).
Cryptographic hash functions have the property that it is extremely difficult to find two different inputs that produce the same output, that is, it is hard to find strings
x != y
such thatH(x) == H(y)
. This is called collision resistance.Since Mercurial uses the SHA-1 function to compute the changeset ID, you get the same changeset ID for identical inputs (identical changes, identical committer names and dates). However, if you use different inputs (
x != y
) when you will get different outputs (changeset IDs) because of the collision resistance.Put differently, if you do not get different changeset IDs for different input, then you have found a collision for SHA-1! So far, nobody has ever found a collision for SHA-1, so this will be a major discovery.
In more detail, the SHA-1 hash function is used in a recursive way in Mercurial. Each changeset hash is computed by concatenating:
and then running SHA-1 on all this (see changelog.py and revlog.py). Because the hash function is used recursively, the changeset hash will fix the entire history all the way back to the root in the changeset graph.
This also means that you wont get the same changeset ID if you add the line
Hello World!
to two different projects at the same time with the same commit message -- when their histories are different (different parent changesets), the two new changesets will get different IDs.Mercurial 的变更集 ID 是每个变更集“清单”的 SHA-1 哈希值。它仅打印全局 ID 的前十几个十六进制数字,但它使用完整的 SHA-1 进行内部操作。没有实际保证它们是独一无二的,但对于实际目的来说这不太可能。
请参阅此处了解详细信息。
Mercurial's changeset IDs are SHA-1 hashes of the "manifest" for each changeset. It only prints the first dozen hex digits of the global ID, but it uses the full SHA-1 for internal operations. There's no actual guarantee that they are unique, but it is sufficiently unlikely for practical purposes.
See here for gory details.