git说“正在解决三角洲”时,实际上在做什么?


Answers:


54

Git使用增量编码将一些对象存储在packfiles中。但是,你不希望有播放的每一个修改,以获得最新的版本在给定的文件,这样的Git还具有存储和文件内容偶尔的快照。“解决差异”是确保所有内容保持一致的步骤。

这是 Pro Git书的“ Git Internals”部分中的一章,该可以在线获取,并对此进行了讨论。


80
这个答案是不正确的。它似乎是在描述Mercurial的工作原理,而不是Git。Google搜索中即将出现此问题,因此我认为需要回复。混帐并没有存储提交作为增量之间的差异; Git是一个“整个对象”商店。因此,Git不需要“快照”来显示任何给定的文件,因为不需要从增量重建文件历史记录。这就是Mercurial的工作方式。
连结说

12
增量编码唯一起作用的地方是打包文件,该文件严格用于压缩和传输-它不会改变Git“看”世界的方式。(kernel.org/pub/software/scm/git/docs/v1.6.2.3/technical/…)请参阅以下araqnid的答案以获得准确的答案。
连结说

4
在此上下文中,所有“快照”均表示文件状态的完整副本,而不是增量编码版本。正如您提到的,Git 确实在packfiles 使用增量编码。没有人说它“改变了Git如何看待世界”。请停止推测自己的假设。
2013年

2
您的答案仍然不正确。“ Git还偶尔会存储文件内容的快照。” -这是不正确的。“'解决三角洲'是确保所有步骤保持一致的步骤。” -这也不正确,araqnid在下面的回答是正确的。
nexus说

1
如上述章节所述,Git始终存储最新版本的完整文件内容。以前的版本为“松散”文件时,它们将存储为增量编码文件。git gcGit会定期(通过调用或在Git认为有必要时进行压缩)将所有“松散”文件压缩到一个packfile中,以节省空间,并在该packfile中创建一个索引文件。因此,zlib将使用其自己的增量算法进行压缩,但是Git确实使用增量编码来存储以前的版本。由于最常见和最频繁的访问是最新版本,因此将其存储为快照。
BrionS

118

的阶段为git clone

  1. 接收回购数据库中所有对象的“打包”文件
  2. 为接收到的包创建索引文件
  3. 检查头部修订(显然是非裸仓库)

“解决增量”是第二阶段显示的消息,索引了打包文件(“ git index-pack”)。

打包文件中没有实际的对象ID,只有对象内容。因此,要确定对象ID是什么,git必须对数据包中的每个对象执行decompress + SHA1生成对象ID,然后将其写入索引文件。

打包文件中的对象可以存储为增量,即要对某些其他对象进行的一系列更改。在这种情况下,git需要检索基础对象,应用命令,然后将结果SHA1。基础对象本身可能必须通过应用一系列增量命令来派生。(即使在克隆的情况下,也已经遇到了基础对象,但是在内存中缓存了多少个制造对象是有限制的)。

总而言之,“解决增量”阶段涉及对整个回购数据库进行解压缩和校验和,这并不奇怪,需要相当长的时间。估计解压缩和计算SHA1实际上比应用delta命令花费更多的时间。

在后续提取的情况下,接收到的包文件可能包含对接收git预期已经具有的其他对象的引用(作为增量对象库)。在这种情况下,接收方git实际上会重写接收到的包文件以包括任何此类引用的对象,从而使任何存储的包文件都是自给自足的。这可能是消息“解决增量”的来源。


7
可以并行化吗?
brooksbp

这种增量压缩是否比将多个对象存储在一个zlib数据流中还重要?
2015年

1
@FUZxxl是的,这是一个使用的diff或xdelta的算法来比较两个斑点,并产生一个编辑的脚本
araqnid

@brooksbp:只有限制。因为ID为103fa49的对象可能需要对df85b51进行解码,但是当您收到103fa49时,df85b51尚不存在(打包文件严格按sha1哈希排序)。因此,对于仅引用现有内容的所有内容,事情都很容易,但是对于其他所有内容,则必须等到收到为止。而且这种增量压缩可以嵌套,因此103fa49可能需要4e9ba42,而这又需要29ad945,而这又需要c9e645a...。[是的,我注意到已经> 4年了;)]
Bodo Thiesen

2
@brooksbp:事实证明,我错了,打包文件不需要按sha1哈希排序。同样,在编写时,git在需要对象之前先写入需要的对象。因此,实际上您应该能够并行化它。唯一的缺点仍然存在:因为您不知道以后需要哪些对象,因此必须一遍又一遍地重新创建一些对象。在这里看到:kernel.org/pub/software/scm/git/docs/technical/...
博德Thiesen

4

琥珀似乎正在描述Mercurial或类似产品使用的对象模型。Git不会存储对象的后续版本之间的增量,而是每次都存储对象的完整快照。然后,它使用增量压缩来压缩这些快照,从而尝试找到要使用的良好增量,而不管它们在历史记录中的位置如何。


5
实际上,尽管Git可以存储松散的对象,但是它们不一定总是这样存储-因为可以删除松散的对象并用打包的内容替换。我不认为Amber的答案在任何有关后续版本的内容上都可以说。
AlBlue 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.