TL;DR:使用--depth 2。继续阅读以了解原因。
浅克隆(可以,但不一定必须)破坏了一项重要的优化。在您的情况下,这发生在第一次推送中,但不会发生在后续推送中。可能会发生其他失败案例,因此其他推送也可能很慢。
我们从一个事实开始,Git 确实是关于提交的,1 它被塑造成一个有向无环图。该图具有顶点或节点(无论您喜欢哪个术语),它们按提交哈希 ID 进行编号。这里相对无关紧要,但有助于具体化的是,节点之间的边/弧作为节点本身的一部分存储,而不是单独保存。每个节点都存储其前任节点的哈希 ID。
存储库本质上是这些提交对象的数据库。一个完整的非浅层存储库具有整个图,从每个根到每个提示提交。 single-branch 克隆可能会丢弃图表的某些部分,但在图表中永远不会有任何“间隙”。例如,给定:
node--node--tip1
/
root--node
\
node--node--tip2
我们可以删除该行上的任一tip 和节点,但不能删除中间行的节点和根。那么,在所有这些情况下,我们都可以——就像 Git 一直做的那样——从尖端开始,向后工作,最终到达根部。
现在,每个节点有两个属性在这里很重要:
这意味着,如果我们在发送方的每一侧都有一个 无间隙 存储库——一个完全完整的存储库,或者至少与它所包含的提示提交一样完整。 -to-receiver 操作,我们可以让 sending 存储库简单地通过它们的编号为我们枚举一组提交。如果我们,接收存储库,缺少该提交,我们要求发送者发送它,并告诉我们其父提交的数量。发件人这样做,我们看看我们是否有这些提交。对于我们缺少的任何内容,我们要求发件人发送这些内容,并告诉我们他们的父提交的数量,等等。
这意味着如果我们有:
node--node--tip1
/
root--node
\
node--node--tip2
和他们有:
node--node--tip1--new
/
root--node
然后他们将宣布使用提交new的哈希ID。我们没有那个,所以他们应该把它添加到一堆提交中发送,并向我们宣布提交tip1 的哈希 ID。我们确实有tip1,所以我们只是告诉他们:我们已经有tip1:你不需要发送它。
这是优化:我们刚刚告诉他们我们的每一次提交,从 tip1 一直到 root。 我们的不,谢谢,我们有一个对他们回复的提议我可以给你发tip1告诉他们不仅有一个提交及其文件,还告诉他们每个前任提交和所有他们的文件也是如此。
他们现在知道,当他们向我们发送提交 new 时,他们只需要发送未出现在先前提交中的树和 blob(“文件”)对象。此外,他们可以压缩这些从tip1 一直到root 的任何先前 提交中的树和blob 对象对树和blob 对象。因此,与发送整个提交所需的数据相比,发送者可以发送远更少的数据,以及每个文件的完整快照。
树对象和blob对象主要是通过提交找到的。带注释的标签对象为图片添加了一个小皱纹,而具有直接指向树或 blob 的带注释的标签会增加另一个,但都不会破坏标准优化。
与发件人是浅存储库时的比较
浅存储库是其中一些提交被人为标记为根提交的存储库。提交对象实际上有正确的父哈希 ID,但是这个提交对象所在的 Git 有一个文件2 上面写着:我们对提交的父对象一无所知@987654335 @。不要试图寻找任何东西:假装tip1 是一个根提交,没有父母。
这意味着发送 Git,而不是:
node--node--tip1
/
root--node
刚刚:
slightly-mangled-tip1
在这个存储库中,我们添加了新的提交:
slightly-mangled-tip1--new
现在我们让我们的 Git 调用他们的 Git 并为其提供新的提交。首先我们提供new。他们说我没有那个,你还能发什么?我们会提供slightly-mangled-tip1,但我们不能这样做,因为当我们读到它时,我们把它弄坏。所以我们说:抱歉,这就是我们为您准备的全部内容。
他们说:那么,给我们发送 commit new。
然后,我们查看提交new。它具有每个文件的完整快照。我们不知道他们是否有任何这些文件。所以我们把整个东西打包并发送all。
他们全部收到,解压,发现我们已经复制了他们已有的 99%,忽略了额外的副本,并接受新的提交并将其放入他们的存储库中:
node--node--tip1--new
/
root--node
\
node--node--tip2
下次我们运行 git push 时,我们有这个:
slightly-mangled-tip1--new--new2
我们为他们提供new2;他们说我没有那个,它的父母是什么,我们说new,他们说我有那个,别费心发送它。这一次,我们看到他们已经拥有几乎每个文件,并且不必费心发送所有那些树和 blob 对象并且可以根据提交new 中的内容。 (我们仍然不能使用稍微管理过的tip1 提交,当然也不能使用任何丢失的先前提交,但是能够消除所有未更改的文件是巨大的。)
2或者其他机制,不过目前是一个名为.git/shallow的文件。
你能做些什么
鉴于您打算运行git push,您将通过在“浅接枝点”和分支尖端“之间”进行一次未损坏的提交获得很多里程。你的git clone 和--depth 2 也是如此。你会得到一个稍微大一点的客户端 Git 存储库,但是第一个 git push 会更快。
也就是说,您将从:
slightly-mangled-node--tip1
在客户端。第一次 new 提交将导致:
slightly-mangled-node--tip1--new
这一次你的 Git 将能够在第一次推送期间向他们的 Git 提供 tip1,这将触发优化。