GIT 下载什么?

What does GIT download?

如果我克隆一个有 3 个分支的存储库。 GIT 是否足够聪明,只下载分支之间的更改,还是为所有分支重复下载所有文件?还有,它是一开始就从所有分支下载所有数据还是等到我切换分支?

Is GIT smart enough to only download the changes between the branches or does it download all files repeatedly for all branches?

关于 git 的最好的事情(来自 git 之前的所有那些)是使用 DAG 来跟踪变化。也就是说,当您 git pullgit fetch 时,它只会下载 diff
所以回答你的问题:它只下载你所做的 3 次提交。然后为您制作一个本地 DAG。查看 here 快速了解 git 基础知识。

And also, does it download all data from all branches at the beginning or waits till I switch the branch?

当您执行 git clone 下载整个存储库时,这是为了构建 DAG。然后稍后它只下载你要求的那些,使用 git fetchgit pull.

git fetch 从远程下载更改并将其存储在 .git/refs/remotes/<remote>/ 中。所以你不会直接把它带进你的working directory。 (如果您不知道 working directory 是什么,请阅读 git baiscs)。
git pull 在一个命令中执行 git fetchgit merge

请参阅其他 SO question 获取与拉取。

一些阅读材料
Git 看起来更像一棵树而不是图形。 SO question
git 的简单介绍,解释我们如何以及为什么使用 DAG Link

git clone 将下载足够的内容,使您能够到达任何分支历史记录中的任何提交。

如果你只想下载每个分支的最高提交,或者只下载每个分支历史的一部分(比如:最后 10 次提交),请查看以下选项:

  • --depth=x
  • --shallow-since=date
  • --shallow-exclude=revision

这些选项也可以传递给 git fetchgit pull


但是请注意,git 旨在高效传输所有内容:

  • 如果一个文件没有被修改(在两次提交之间)它只会被下载一次
  • 所有下载的内容都被压缩(使用zlib
  • 它有很多功能可以检测到 2 个文件非常相似并只下载差异(而不是整个内容的两倍)

当前接受的答案相当具有误导性,它所说的很多内容并没有真正解决问题。

只有打包表示[1] 用于回购协议之间的传输,因此您通常可以假设您将收到(合理的)最少的所请求信息的表示。

说它 "only downloads the commits" 有几个原因是误导。大多数情况下,它助长了一种误解,即提交本身就是更改列表——但它们不是。提交是项目的快照[2]。 "Downloads the commits" 大致意思是 "downloads everything".

这是一个很好的转折...

默认情况下 git clone 下载所有分支的完整历史记录。如果你知道你需要更少,你可以给它选项来告诉它下载更少,但默认是下载所有东西,这样你以后可以在没有任何必要连接的情况下执行任何源代码控制操作(除了与另一个 repo 同步更改)。有关选项的详细信息,请参阅 git clone 文档 (https://git-scm.com/docs/git-clone) - 特别是 --single-branch--depth--shallow-* 选项。

None 其中确实与 DAG 表示有很大关系。这仅在考虑如何在 git 中导航对象时才真正重要,事实上,将增量视为遵循 DAG 是错误的,因为您通常会倒退。


[1] git 有两种格式存储构成项目历史的对象。当提交新 material 时,它存储在松散对象中 - 每个文件每个版本的完整副本 - 但即便如此,git 也永远不会存储 相同的 内容两次。因此,如果一个文件在 10 次提交中没有更改,那么将存储该文件的一个副本。此外,即使是松散形式的数据也会被压缩。

稍后,对象可以切换为 "packed" 表示。打包时所做的优化之一是找到相似的对象,并将两者的 older 表示为 newer.[=18= 的增量]


[2] 一些命令,比如 rebase,在提交和它的父提交之间的 补丁 上运行,以及文档(就像很多 git文档)对这些命令的术语有点模糊。所以不幸的是,很容易误认为提交是要传播的更改列表。

但是,即使构成较旧提交的某些对象可能在内部表示为来自较新提交的其他对象的增量,从概念上讲,提交 快照。如果你告诉 git,例如使用 --depth 选项,只下载特定提交的部分内容,您仍然会获得整个快照——而不仅仅是与之前提交相关的补丁。包含部分增量但没有足够信息来重建快照(即提交)的回购协议的任何子集都将被视为已损坏。