说,我有一个包含内容的文件:
1111
2222
3333
然后我将其修改为:
1111
2222
4444
3333
Git是否会使用较新版本生成新文件?我很困惑,如果它创建了新文件,那么整个存储库的大小会很快增长吗?
另一个想法是,Git不创建新文件,只存储添加位置或删除行的位置,并存储新行内容。
哪一个是正确的?
答案 0 :(得分:4)
许多较旧的源代码管理系统(如RCS和CVS)专门在文件版本之间存储差异。例如,给定源文件的信息可能以包含最新版本全文的形式存储在存储库中,另外还有用于生成早期版本的“指令”。
Git,至少在概念上,将每个文件的每个版本的全部内容存储在存储库中。它只存储一个相同文件的副本,从而节省了一些空间,因为用于存储它的名称是通过散列内容来确定的。
显然,如果这是整个故事,Git存储库会很快变得非常大。但Git会自动打包或压缩存储的对象。坦率地说,我不知道所有细节,但它在很小的存储空间和允许快速重新创建任意版本方面做得很好。
例如,Git源本身存储在Git存储库中,该存储库可能包含数千个不同的对象。所有文件的所有版本都存储在目录.git/objects/pack
下,目录中包含以下内容(列表是我系统上的克隆):
$ ls -l .git/objects/pack
total 48900
-r--r--r-- 1 kst kst 4196172 Mar 20 15:44 pack-0e69de7b7728ad0fde80423ded259dbff7760016.idx
-r--r--r-- 1 kst kst 36698393 Mar 20 15:44 pack-0e69de7b7728ad0fde80423ded259dbff7760016.pack
-r--r--r-- 1 kst kst 125896 Jun 30 22:17 pack-2848a675d3c196391f06cc7cdd6cebf67fb7119e.idx
-r--r--r-- 1 kst kst 3570770 Jun 30 22:17 pack-2848a675d3c196391f06cc7cdd6cebf67fb7119e.pack
-r--r--r-- 1 kst kst 178452 May 16 08:22 pack-bfd75de39dff6ac03adcc775f7b5715480b54637.idx
-r--r--r-- 1 kst kst 5292998 May 16 08:22 pack-bfd75de39dff6ac03adcc775f7b5715480b54637.pack
与早期系统(至少对我之前使用过的系统)相比,Git有什么不同之处在于,在较高的层次上,存储库中所有文件的所有版本都是完整存储的,但压缩是由一个单独的层。
答案 1 :(得分:1)
Git只存储项目内容的变化。增量差异。在任何给定的时间点,任何与某个先前文件相同的文件被记录为指向描述该在先文件内容的对象的指针。它对文件内容使用散列来了解文件何时发生更改以及查找与先前版本的匹配,因此它不必多次存储相同的内容。
它还有一个简单的数据库,用于描述所有变化及其关系。
以下是有关如何组织存储库的一些文档:
https://www.kernel.org/pub/software/scm/git/docs/gitrepository-layout.html
关于节省空间的补充说明:Git的大空间节省结果是两次不存储相同的文件。其他内容管理器不像Git那样使用指向文件版本的指针,这样可以在项目版本的生命周期内节省大量资金。由于项目的移动版本只有少数文件发生变化。
答案 2 :(得分:1)
对于普通文件,git将它们存储为blob
个对象,git将每个版本的文件存储为单独的blob
。所以它们是分开存储的。这样做的好处是,您可以非常快速地检查一些提交(而不是回溯和执行所有修补操作)。
对于存储库大小问题,git提供了一个对象打包机制并自动压缩数据(或根据您的要求)。在大多数情况下,这不是一个大问题。