检查两个git存储库是否不相关的简单方法是什么?

检查两个git存储库是否不相关的简单方法是什么?,git,Git,检查两个git存储库是否不相关的简单方法是什么 例如,假设我们克隆了以下存储库: 我如何检查一个不与另一个共享历史 我如何检查一个与另一个共享部分历史记录?如何浏览常用DAG和查看差异 注意:Git允许浅拷贝+存储库历史可以随时间而变化…您可以克隆第一个存储库,然后将第二个存储库添加为其他远程存储库: git clone https://github.com/spring-petclinic/spring-framework-petclinic cd spring-framework-p

检查两个git存储库是否不相关的简单方法是什么

例如,假设我们克隆了以下存储库:

我如何检查一个不与另一个共享历史

我如何检查一个与另一个共享部分历史记录?如何浏览常用DAG和查看差异


注意:Git允许浅拷贝+存储库历史可以随时间而变化…

您可以克隆第一个存储库,然后将第二个存储库添加为其他远程存储库:

git clone https://github.com/spring-petclinic/spring-framework-petclinic
cd spring-framework-petclinic
git remote add other https://github.com/spring-projects/spring-petclinic
git fetch --all
然后可以浏览两个DAG:

git log --graph --all --oneline --decorate
通过查看两个主干的合并基础,查看它们是否有任何共同的历史:

git merge-base origin/master other/master

您可以克隆第一个,然后将第二个添加为附加远程:

git clone https://github.com/spring-petclinic/spring-framework-petclinic
cd spring-framework-petclinic
git remote add other https://github.com/spring-projects/spring-petclinic
git fetch --all
然后可以浏览两个DAG:

git log --graph --all --oneline --decorate
通过查看两个主干的合并基础,查看它们是否有任何共同的历史:

git merge-base origin/master other/master

很容易证明两个存储库是相关的:如果它们包含具有相同散列ID和内容的匹配提交,尽管“相同散列ID”通常就足够了1它们是相关的

正如您所注意到的,除非它们都是完整的(非浅层、非单分支)克隆,否则要证明它们是不相关的要困难得多。如果两个存储库都是完整的,但都没有与另一个相同的提交,那么这两个存储库是不相关的

如果您拥有两个存储库并验证它们都是完整的,只需枚举两个存储库中的所有提交哈希ID并查找公共ID。如果存在公共ID,则两者可能是相关的。要枚举所有提交散列ID,请运行
git rev list--all
(将输出重定向到读取两组输出并检查公共散列ID的文件或程序)

请参见脚注1,删除“可能”,但TL;现在,任何两个相同的ID都意味着共享历史


1给定一个范围为r={h(k)|的统一散列函数h(k),两个不同键k1,k2的散列意外碰撞的概率为p=1/r。唯一性概率是该函数的补充,即p̄=1-(1/r)。推广到n个键,并使用≈ 1+x代表x≪ 1,我们得到p̄≈e(-n(n-1))/2r,只要r相当大

Git的散列函数目前是SHA1,它的分布非常均匀,r=2160=14615016373002918203684832716283019655932542976。这满足了我们的公式,这意味着我们可以使用近似值

因此,如果将哈希总数n相加并将其插入公式:

r=1461501637330902918203684832716283019655932542976
1 - exp(-n*(n-1)/(2*r))
(记住,我们想要的是p,不是p-bar), 您可以得到冲突的概率。当然,要检查实际的冲突,您可以只比较底层的实际对象:如果哈希匹配,则直接比较对象以检测冲突。但这在一开始是极不可能的。如果我们将两个存储库合并在一起,包含一千万次提交,我们计算:

$ bc -l
r=2^160
n=10*1000*1000
scale=100
1 - e(-n*(n-1)/(2*r))
.0000000000000000000000000000000000342113848680412753525884397196522\
895097282878872708411144841034243
正如你所看到的,它仍然很小。直到我们到达:

n=10*1000*1000*1000*1000*1000*1000*1000
(十个六分仪对象,使用短标度符号)

我们发现:

1 - e(-n*(n-1)/(2*r))
.0000342108030863093209851036344159518189002166758764416221121344549\
079733424124497666779807175655625
意外碰撞的明显概率约为0.0035%。在100个sextillion物体上,我们的概率高达0.35%:

n=100*1000*1000*1000*1000*1000*1000*1000
1 - e(-n*(n-1)/(2*r))
.0034152934013810288444649336362559390942558976421984312395097770719\
923433072593638116228277476790795
到了19亿个目标,我们面临着一些严重的风险:

1 - e(-n*(n-1)/(2*r))
.2897326871923714506502211457721853341644126909116947422293621066225\
555385326652788789421475224989232
幸运的是,在那之前,我们已经用完了磁盘空间。:-)另外,Git的人正在考虑转移到SHA-256散列中的一个,这将把r提高到2256,这有助于我们的分母


(我在上面使用了
bc
,其中
^
是指数运算,
-l
库添加了
e(x)
来计算ex.)

很容易证明两个存储库是相关的:如果它们包含具有相同哈希ID和内容的匹配提交,尽管“相同哈希ID”通常只要它们是相关的就足够了

正如您所注意到的,除非它们都是完整的(非浅层、非单分支)克隆,否则很难证明它们是不相关的。如果两者都是完整的,但都没有与另一个相同的提交,则这两个存储库是不相关的

如果您拥有两个存储库并验证它们都是完整的,只需枚举两个存储库中的所有提交哈希ID并查找公共ID。如果存在公共ID,则这两个ID可能是相关的。要枚举所有提交哈希ID,请运行
git rev list--all
(将输出重定向到读取两组输出并检查公共哈希ID的文件或程序)

太长了,读不下去了,但是现在的TL;DR是,任何两个相同的ID意味着共享的历史。


1给定一个范围为r={h(k)|的统一散列函数h(k),两个不同键k1,k2的散列意外碰撞的概率为p=1/r。唯一性概率是该函数的补充,即p̄=1-(1/r)。推广到n个键,并使用≈ 1+x代表x≪ 1,我们得到p̄≈e(-n(n-1))/2r,只要r相当大

Git的散列函数目前是SHA1,它的分布非常均匀,r=2160=14615016373002918203684832716283019655932542976。这满足了我们的公式,这意味着我们可以使用近似值

因此,如果将哈希总数n相加并将其插入公式:

r=1461501637330902918203684832716283019655932542976
1 - exp(-n*(n-1)/(2*r))
(记住,我们想要的是p,不是p-bar), 您可以得到冲突的概率。当然,要检查实际的冲突,您可以只比较底层的实际对象:如果哈希匹配,则直接比较对象以检测冲突。但这在一开始是极不可能的。如果我们将两个存储库合并在一起,包含一千万次提交,我们计算:

$ bc -l
r=2^160
n=10*1000*1000
scale=100
1 - e(-n*(n-1)/(2*r))
.0000000000000000000000000000000000342113848680412753525884397196522\
895097282878872708411144841034243
正如你所看到的,它仍然很小。直到我们到达:

n=10*1000*1000*1000*1000*1000*1000*1000
(十个六分仪对象,使用短标度符号)

我们发现:

1 - e(-n*(n-1)/(2*r))
.0000342108030863093209851036344159518189002166758764416221121344549\
079733424124497666779807175655625
意外碰撞的明显机会