git "shallow clone + unshallow"与 "normal clone"

标签 git git-clone

我看过这个答案for a git clone error ,建议不要克隆整个 repo,而是只克隆最新的提交,然后使用 unshallow 获取其余的提交。

考虑以下两个命令

1. 
git clone <url> --depth 1
git fetch --unshallow

2. 
git clone <url>

两者克隆的最终输出是否相同? 如果是这样,对于非常大的存储库,为什么第二个命令比第一个命令运行得快得多?

是否还有其他浅层克隆不能做的事情,或者有一些缺点,特别是在处理大型存储库时?

最佳答案

当您克隆一个非常大的存储库时,您需要传输大量数据。根据您的网络速度,这可能需要很长时间。为了输入一些具体数字,让我们使用 10 GiB 作为整个存储库数据传输大小(数据传输大小和磁盘上的大小会有所不同,但通常相差不大)并假设您可以获得的传输速率1 兆字节/秒。这意味着数据传输需要 10240 MiB/(1 MiB/s) = 10240 s = 170.667 分钟 = 不到 3 小时(大约 2 小时 50 分钟)。

正在使用的各种协议(protocol)内置了错误检测和(通常在硬件级别)校正,但在此期间连接仍有可能失败。如果连接确实失败,git clone 将整个事情视为原子:没有一个有效,因此 Git 将删除整个克隆。

如果使用 --depth 1 进行抓取导致初始克隆仅复制整体数据的大约 1/3,我们将克隆时间减少到大约 1 小时,从而降低了以下风险彻底失败也是如此。然后可以增量地添加到浅层克隆(使用 --deepen 或更大的 --depth 数字到 git fetch)。其中每一个都有自己的失败风险,但失败只会导致不添加任何对象:现有的克隆没有受到伤害。根据需要重试一个小时的传输比重新启动整个 3 小时的传输只是在 2 小时 20 分钟内失败要轻松得多。1

最终,最后的 --unshallow 会为您提供所有您可能会得到的东西,如果您能够同时无误地进行完整克隆的话。请注意,您可能希望在初始浅克隆期间使用 --no-single-branch,或者在初始浅克隆之后修复获取 refspec。

Is the final output of the clone the same for both?

这个问题的答案既不是也不是。我们需要准确定义“最终输出”的含义。但是,就对所有提交和其他对象的有用访问而言,结果是相同的(假设您撤消了 --depth 参数的单分支效果)。

If so, how is it that the second command works much faster than the first for a very large repo?

它不一定工作得更快。然而,在进行完整克隆时,Git 可以——不一定,但可以——只发送一个现有的包文件,而不是构建一个新的包文件。这可以节省发送方的 CPU 时间。如果发送方的(单个)打包文件构造良好,则接收方生成的单个打包文件也构造良好。使用浅层克隆或什至单个非浅层进行重复加深的结果通常会在接收器上产生多个包文件;这些可能构造得不太好。


1这里我说的是实际经验。 :-) 现在的传输速率比 2005 年不稳定的 DSL 布线要高,但存储库现在也更大了。而且,即使是现在,美国在某些地方的互联网基础设施也很糟糕。

关于git "shallow clone + unshallow"与 "normal clone",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67838180/

相关文章:

reactjs - Bitbucket 管道无法推送到 heroku

git - Buildbot 与 GitPoller 有问题

git - 如何将 Git 存储库中可用的包添加到 Buildroot?

git - 使用 GIT 分支/分支

java - 启用 git lfs 的 Jgit 克隆存储库无法正常工作

git - 致命的 : read error: Connection reset by peer

git 部署项目 - 文件权限 - (chmod)

git - 为 Git 克隆设置密码?

android - 如何在 Android Studio 中从 GitHub 克隆项目

git - 如何设置子模块,以便 git clone --recursive 始终占据子模块的主控