【问题标题】:Hash collision in commits from all version control systems来自所有版本控制系统的提交中的哈希冲突
【发布时间】:2018-01-27 02:43:17
【问题描述】:

我读过Hash collision in git 由此看来,git中两个不同的提交不太可能具有相同的哈希值。

但是不只是 git 的所有提交呢?我的应用程序使用 git,svn,hg - 我可以假设不会有相同哈希的不同提交吗?

现在我正在尝试如何阻止我的应用程序从 db 中一个 repo 的不同分支创建相同的提交。 我弄清楚我可以在 db unique 中做什么哈希列,如果我已经提交了这个哈希 - 只需跳过它。 但我不知道是否有很大/很小的机会我会跳过唯一提交而不是已经存在的提交的副本。

【问题讨论】:

    标签: git svn mercurial sha


    【解决方案1】:

    git 和 mercurial 都使用sha1 来生成哈希,所以我想说两个不同的提交(一个来自 git,一个来自 mercurial)具有相同哈希的概率与两个不同的 git 具有相同哈希的概率相同提交。

    Svn 不使用哈希来识别提交,而是使用增量修订号,因此您在这里不会遇到任何冲突问题

    【讨论】:

    • 当我通过pygit 加载 whem 时,我使用 git svn 与 svn repos 一起工作,所以它们在我的代码中有一个哈希值。感谢回复
    • 所以同样适用于 hg 的推理
    【解决方案2】:

    TL;DR:除非你混合 VCS,否则你是安全的。


    您问题中的问题陈述首先不太正确:

    ... git 中的两个不同提交似乎不太可能具有相同的哈希值。

    这(间接)导致错误的进一步假设:

    但是不只是 git 的所有提交呢?我的应用程序使用 git,svn,hg - 我可以假设不会有相同哈希的不同提交吗?

    即使所有的 VCS 都是完美的,你也不能真正做出这样的假设。即使所有的 VCS 都是完美的并且使用相同的散列算法,你仍然不能做出这样的假设。但是对于您的特定问题,有一个更简单(尽管不完美)的答案。

    现在我正在尝试决定如何阻止我的应用程序从 db 中一个 repo 的不同分支创建相同的提交...

    这里要考虑的主要问题是“一个 repo 的分叉”的概念,以及您将如何识别特定的提交。

    如果我们在 Git 或 Mercurial 中查看提交的身份,我们会发现它一个哈希 ID。

    Git 中具有相同对象 ID 的两个对象根据定义,是同一个对象,因为 Git 只会存储任何对象一次。这是因为 Git 的底层存储模型是一个简单的键值存储,键是一个哈希 ID。任何一个键下都只存储一个值。

    为了允许 Git 中的四种对象类型——提交、注释标签、树和 blob——Git 将对象的类型存储在所有对象前面的标头中。它假设将字符串 commit <size>\0 附加到某些数据会导致与将字符串 blob <size>\0 附加到相同数据不同的哈希值。这个假设在很大程度上是正确的,尽管鸽巢原理告诉我们一定有一些数据是错误的。 (在 SHA-1 好的范围内,找到产生冲突的数据对的机会是 2160 中的 1 个。Stevens 等人的工作表明 SHA-1 不是那么好.)

    不过,无论如何,Git 的底层存储模型意味着一旦一个键有一个关联的值,该键/值对现在就被占用了,并且没有与 相同的对 em> 密钥可以再次存储。因此,如果某个现有的键 k 存在,并且具有类型 commit 并表示某个提交,则没有具有键 any 类型的新对象k 可以添加到存储库数据库中(至少在没有首先使用键 k 删除现有对象的情况下不能)。

    这意味着如果你假设提交没有被删除,并且如果你已经看到密钥 k 之前存在于这个存储库的任何克隆中,那么任何 other em> 带有键 k 的克隆具有 same 对象。散列,换句话说,对象,在非常真实的意义上。

    在 Mercurial 中不一定是这种情况。 Mercurial 的数据库可以存储具有重复键的新提交(与每个对象关联的简单本地序列号可以消除它们的歧义)。但是,此类提交永远不能从一个存储库转移到另一个存储库(并且可能会导致其他问题),因此如果存储库将被分发,您当然可以假设问题已解决。

    目前,Git 和 Mercurial 都使用 SHA-1,但它们以不同的方式使用。也就是说,在 Git 和 Mercurial 中计算哈希的输入消息是不同的。 this 的意思是,如果你有代表相同 repository,G 中的键 kG (在数字上)与键无关 kMM.

    因此,如果您允许两个不同的分叉使用两个不同的底层 VCS,则不能假设两个不同的键代表两个不同的对象,也不能假设两个相同的键代表同一个对象。但是,如果您将它们限制在 same VCS,您可能会做出这样的假设。

    (SVN 根本不通过哈希来识别提交。由于 SVN 存储库是中心化的,它们可以并且确实使用一个简单的唯一整数来表示每个提交。但是,通过将 SVN 存储库转换为 Git 存储库,您将 Git限制:您现在拥有一个满足 both VCSes 施加的任何限制的存储库。如果有人向 SVN 存储库添加了一个无法在 Git 存储库中正确表示的新提交,它根本不会进入 Git存储库。)

    【讨论】:

      猜你喜欢
      • 2016-06-25
      • 2012-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-31
      • 2016-07-30
      • 1970-01-01
      相关资源
      最近更新 更多