git如何存储文件?

我刚开始学习git,为此我开始阅读Git社区书籍 ,在这本书中,他们说SVN和CVS存储文件之间的差异,而git存储所有文件的快照。

但我并没有真正明白他们的意思。 git是否真的在每个提交中创build了所有文件的副本,因为这是我从他们的解释中理解的。

PS:如果任何人有更好的学习git的来源,我将不胜感激。

Git确实为每个提交存储了所有文件的完整副本,除了对于已经存在于Git仓库中的内容,快照将简单地指向所述内容而不是复制它。
这也意味着几个具有相同内容的文件只被存储一次。

所以快照基本上是一个提交,指的是一个目录结构的内容

一些很好的参考是:

  • gitref.org

你告诉Git你想用git commit命令保存项目的快照,它基本上logging了项目中所有文件的外观

  • 混帐沉浸

实验12说明了如何获取以前的快照

  • “ 你可以发明git(也许你已经拥有了!) ”

  • 什么是git“快照”?

  • 学习GitHub


本书对快照有更全面的描述:

Git和其他任何VCS(包括Subversion和朋友)之间的主要区别在于Git认为它的数据的方式。
从概念上讲,大多数其他系统将信息存储为基于文件的更改列表。 这些系统(CVS,Subversion,Perforce,Bazaar等)将它们保存的信息视为一组文件,并对每个文件随时间的变化

基于增量的VCS

Git不会这样想或存储数据。 相反,Git认为它的数据更像是一组迷你文件系统的快照。
每当你提交或保存你的项目在Git中的状态,它基本上就是你所有的文件在这个时候的样子的图片,并存储对该快照的引用。
为了高效,如果文件没有改变,Git不会再存储文件 – 只是一个链接到它已经存储的前一个相同的文件。
Git认为它的数据更像下面这样:

基于快照的VCS

这是Git和几乎所有其他VCS之间的重要区别。 这让Git几乎重新考虑了大多数其他系统从上一代复制的版本控制的各个方面。 这使得Git更像是一个迷你文件系统,在其上面build立了一些令人难以置信的强大工具,而不仅仅是一个VCS。


扬·胡德克(Jan Hudec)补充道:

虽然这在概念层面上是真实的和重要的,但在存储层面却不是这样。
Git使用deltas进行存储
不仅如此,它比其他任何系统都更有效率。 因为它不保留每个文件的历史logging,所以当它想要进行增量压缩时 ,它需要每个blob,select一些可能相似的blob(使用启发式,包括最近似的先前版本和其他一些),尝试生成三angular洲,并select最小的一个。 这样它可以(通常取决于启发式)利用其他类似的文件或比以前更类似的老版本。 “包窗口”参数允许交易性能为增量压缩质量。 默认值(10)通常会得到相当好的结果,但是当空间有限或加速networking传输时, git gc --aggressive使用值250,这使得它运行得非常慢,但是为历史数据提供额外的压缩。

Git在逻辑上将每个文件存储在其SHA1下。 这意味着如果在存储库中有两个具有完全相同内容的文件(或者如果您重命名文件),则只会存储一个副本。

但是这也意味着当你修改文件的一小部分并提交时,文件的另一个副本被存储。 git解决这个问题的方法是使用包文件。 有一段时间,所有的“松散”文件(实际上,不仅仅是文件,而且包含提交和目录信息的对象)都被收集并压缩成一个包文件。 包文件使用zlib进行压缩。 而类似的文件也是delta压缩的。

拉或推时也使用相同的格式(至less有一些协议),所以这些文件不必再次压缩。

这样做的结果是,一个包含整个未压缩工作副本,未压缩最近文件和压缩旧文件的git仓库通常比较小,比工作副本的两倍小。 这意味着即使SVN没有在本地存储历史logging,它也会比SVN还小的文件。

是的,git确实做了一个文件的副本。 理念是,在大多数情况下,磁盘空间本质上是免费的。

这就是为什么在使用git时通常不会跟踪大型资源(video,录音等)的原因。 例如,参见这个讨论 。

PS拉尔斯·沃格尔(Lars Vogel)在这里做了一个很好的介绍。

上面的答案是相当正面的,但我想添加一个更小的小概念,即增量编码。 保存效率直到包文件被写入。 在每次提交时,松散对象都以压缩格式写入,但不是三angular洲格式。