我刚开始学习git并且这样做我开始阅读the Git Community Book,在本书中他们说SVN和CVS存储了文件之间的差异,而git存储了所有文件的快照。
但是我并没有真正了解快照的含义。 git是否真的复制了每个提交中的所有文件,因为这是我从他们的解释中理解的。
PS:如果有任何人有更好的学习git的来源我会很感激。
答案 0 :(得分:228)
Git确实为每个提交包含了所有文件的完整副本,但对于Git存储库中已存在的内容,快照只会指向所述内容而不是复制它。
这也意味着具有相同内容的多个文件只存储一次。
因此,快照基本上是一个提交,指的是目录结构的内容。
一些很好的参考资料是:
你告诉Git你想用git commit命令保存项目的快照,它基本上记录了项目中所有文件在那时的样子的清单
Lab 12说明了如何获取以前的快照
progit book具有更全面的快照描述:
Git和任何其他VCS(包括Subversion和朋友)之间的主要区别在于Git对其数据的看法。
从概念上讲,大多数其他系统将信息存储为基于文件的更改列表。这些系统(CVS,Subversion,Perforce,Bazaar等)将它们保存的信息视为一组文件以及随时间对每个文件所做的更改
Git没有想到或以这种方式存储数据。相反,Git认为其数据更像是一组迷你文件系统的快照 每次你在Git中提交或保存项目的状态时,它基本上都会记录当时所有文件的样子并存储对该快照的引用。
为了提高效率,如果文件没有改变,Git不会再次存储文件 - 只是指向它已存储的上一个相同文件的链接。
Git认为其数据更像如下:
这是Git与几乎所有其他VCS之间的重要区别。它让Git几乎重新考虑了大多数其他系统从上一代复制的版本控制的每个方面。这使得Git更像是一个迷你文件系统,其上构建了一些非常强大的工具,而不仅仅是一个VCS。
Jan Hudec添加了此important comment:
虽然这在概念层面上是真实而重要的,但在存储层面并非如此 Git确实使用增量存储 不仅如此,它比其他任何系统都更有效率。因为它不保留每个文件的历史记录when it wants to do delta compression,所以它需要每个blob,选择一些可能相似的blob(使用包含最接近的先前版本和其他一些版本的试探法),尝试生成三角洲和最小的一个。通过这种方式,它可以(通常取决于启发式方法)利用其他类似文件或比以前更相似的旧版本。 “pack window”参数允许delta压缩质量的交易性能。默认值(10)通常会得到不错的结果,但是当空间有限或加速网络传输时,
git gc --aggressive
使用值250,这使得它运行速度非常慢,但为历史数据提供额外的压缩。
答案 1 :(得分:37)
Git在逻辑上将每个文件存储在其SHA1下。这意味着如果您有两个文件在存储库中具有完全相同的内容(或者如果您重命名文件),则只存储一个副本。
但这也意味着当您修改文件的一小部分并提交时,会存储该文件的另一个副本。 git解决这个问题的方法是使用pack文件。偶尔,收集来自repo的所有“松散”文件(实际上,不仅仅是文件,还包含提交和目录信息的对象),并将其压缩到包文件中。使用zlib压缩包文件。类似的文件也是delta压缩的。
拉或推时(至少使用某些协议)也会使用相同的格式,因此不必再次压缩这些文件。
结果是git存储库包含整个未压缩的工作副本,未压缩的最新文件和压缩的旧文件通常相对较小,比工作副本的大小小两倍。这意味着它比具有相同文件的SVN repo小,即使SVN没有在本地存储历史记录。