Git 来自所有版本控制系统的提交中的哈希冲突

Git 来自所有版本控制系统的提交中的哈希冲突,git,svn,mercurial,sha,Git,Svn,Mercurial,Sha,我读 由此看来,git中的两个不同提交不太可能具有相同的哈希 但是,除了git之外的所有提交又如何呢?我的应用程序使用git、svn、hg——我能假设使用相同的哈希不会有不同的提交吗 现在,我正试图设计如何阻止我的应用程序从数据库中的一个repo的不同分支创建相同的提交。 我知道我可以在db unique的哈希列中做什么,如果我已经用这个哈希提交了,就跳过它。 但是我不知道我是否有很大/很小的机会跳过唯一提交,而不是现有提交的副本。git和mercurial都使用sha1生成哈希,所以我想说,通

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

但是,除了git之外的所有提交又如何呢?我的应用程序使用git、svn、hg——我能假设使用相同的哈希不会有不同的提交吗

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

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


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

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


Svn不使用散列来标识提交,而是使用增量修订号,因此这里没有任何冲突问题

TL;博士:除非你混合使用VCSE,否则你是安全的


首先,你问题中的问题陈述并不完全正确:

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

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

但是,除了git之外的所有提交又如何呢?我的应用程序使用git、svn、hg——我能假设使用相同的哈希不会有不同的提交吗

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

现在,我正试图设计如何阻止我的应用程序从数据库中一个repo的不同分支创建相同的提交

主要考虑的是“一个回购叉”的概念,以及如何确定一个特定的提交。< /P> 如果我们查看Git或Mercurial中提交的标识,就会发现它是一个哈希ID

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

为了允许Git提交中的四种对象类型,带注释的标记、树和blob Git将对象的类型存储在所有对象前面的头中。它假设将字符串
commit\0
预先添加到某些数据会导致与将字符串
blob\0
预先添加到相同数据不同的哈希值。这个假设基本上是正确的,尽管鸽子洞原理告诉我们一定有一些数据是错误的。(在一定程度上,SHA-1是好的,找到产生碰撞的数据对的几率是2160分之一。Stevens等人的工作表明SHA-1没有那么好。)

不过,无论如何,Git的底层存储模型意味着,一旦一个密钥有了关联的值,该密钥/值对现在就被占用了,并且不能再次存储具有相同密钥的密钥对。因此,如果存在某个现有密钥k,并且具有类型commit并表示某个commit,则不能将任何类型的具有密钥k的新对象添加到存储库数据库中(至少必须先删除具有密钥k的现有对象)

这意味着,如果假设未删除提交,并且在此存储库的任何克隆中看到密钥k之前存在,则具有密钥k的任何其他克隆都具有相同的对象。换句话说,散列就是对象,在非常真实的意义上

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

目前,Git和Mercurial都使用SHA-1,但使用方式不同。也就是说,计算哈希的输入消息在Git和Mercurial中有所不同。这意味着,如果您有代表同一存储库的“fork”G(通过Git存储)和M(通过Mercurial存储),那么G中的键kG(数字上)与M中的键kM无关

因此,如果允许两个不同的分叉使用两个不同的基础VCSE,则不能假设两个不同的键代表两个不同的对象,也不能假设两个相同的键代表同一个对象。但是,如果你将它们限制在同一家风险投资公司,你可能会做出这样的假设


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

TL;DR:除非混合使用VCSE,否则您是安全的


首先,你问题中的问题陈述并不完全正确:

。。