阅读git的文档他们强调的一件事是git存储快照而不是增量.自从我看到Git的课程说Git存储了文件版本之间的差异后,我尝试了以下内容:我在一个空文件夹上初始化了一个git存储库,创建了一个lorem.txt
包含一些lorem ipsum文本的文件,该文件暂存并提交.
然后find .git/objects -type f
在命令行上使用我列出了在对象文件夹上保存的git,并且按照预期找到了一个提交对象,该对象指向指向包含我保存的lorem ispum文本的blob对象的树对象.
然后我修改了lorem ipsum文本,添加了更多内容,暂存了这个更改并提交了.再次列出文件,我现在可以看到新的提交对象,指向一个新的三个对象和一个新的blob对象.使用git cat-file -p 331cf0780688c73be429fa602f9dd99f18b36793
我可以看到新blob的内容.它们正是完整lorem.txt
文件的内容,旧内容加上更改.
这符合文档的预期:git存储快照,而不是增量.但是,在互联网上搜索我发现了这个问题.在接受的答案中,我们看到以下内容:
虽然这在概念层面上是真实而重要的,但在存储层面却并非如此.
Git确实使用增量来存储.
不仅如此,它比其他任何系统都更有效率.因为它不保留每个文件的历史记录,所以当它想要进行增量压缩时,需要每个blob,选择一些可能相似的blob(使用包含最接近的先前版本和其他一些版本的试探法),尝试生成增量并选择最小的增量.通过这种方式,它可以(通常取决于启发式方法)利用其他类似文件或比以前更相似的旧版本."pack window"参数允许delta压缩质量的交易性能.默认值(10)通常会得到不错的结果,但是当空间有限或加速网络传输时,git gc --aggressive使用值250,这使得它运行速度非常慢,但为历史数据提供了额外的压缩.
这说Git确实使用增量进行存储.据我所知,Git不会一直使用增量,但只有在检测到它时才有必要.这是真的?
我在文件上放了很多lorem文本,所以它的大小是2mb.我认为当对一个大文本文件做一个小改动时,Git会自动使用增量,但正如我所说的那样.
当Git使用deltas以及它是如何工作的?
sle*_*ske 10
Git只在"packfiles"中使用增量.最初,每个git对象都被写为一个单独的文件(如您所见).之后,git可以将许多对象打包到一个文件中,称为"包文件".然后压缩包文件,该文件自动利用packfile中文件之间的任何重复(或文件内的重复).
这种包装是由git repack
.您可以通过手动调用它来查看它.如果你git repack -ad
在git repo上运行,你应该看到使用的磁盘空间和.git/objects
drop 下的文件数,因为文件被组合成包并被压缩.
在实践中,您通常不需要运行git repack
.默认情况下git gc
,Git会定期运行,并在git repack
必要时运行.所以放松一下,git有你的背:-).
优秀的"git book"还有一章有关packfiles的更多解释:http://git-scm.com/book/en/v2/Git-Internals-Packfiles .
Git 2.18(2018 年第 2 季度)记录了增量使用情况Documentation/technical/pack-format
请参阅Nguy\xe1\xbb\x85n Th\xc3\xa1i Ng\xe1\xbb\x8dc Duy的提交 011b648(2018 年 5 月 11 日) ( )。\n (由Junio C Hamano 合并 -- --提交b577198,2018 年 5 月 23 日)pclouds
gitster
\n\n\npack-format.txt:有关包文件格式的更多详细信息
\n\n当前文档提到
\n\nOBJ_*
常量,但没有其实际值。git 开发人员会知道这些来自cache.h
,但这对于想要读取此文件来实现包文件解析器的人来说不太友好。同样,增量表示根本没有记录(“文档”基本上是 patch-delta.c)。将 C 代码翻译成\n 英语,并详细说明什么
\nofs-delta
和ref-delta
含义。
所以文档现在指出:
\n\n\n\n\n对象类型
\n\n有效的对象类型有:
\n\n\n
\n\n- \n
OBJ_COMMIT
(1)- \n
OBJ_TREE
(2)- \n
OBJ_BLOB
(3)- \n
OBJ_TAG
(4)- \n
OBJ_OFS_DELTA
(6)- \n
OBJ_REF_DELTA
(7)Type 5 保留用于将来的扩展。类型 0 无效。
\n\n详细的表示
\n\n从概念上讲,只有四种对象类型:提交、树、标记和 blob。
\n\n
然而 ,为了节省空间,一个对象可以存储为另一个“基础”对象的“增量”。
\n 这些表示被分配了新类型 s-delta 和 ref-delta,仅在包文件中有效。两者
\n\nofs-delta
都ref-delta
存储要应用于另一个对象(称为“基础对象”)以重建该对象的“增量”。
\n 它们之间的区别是,\n
\n\n- ref-delta 直接编码 20 字节的基础对象名称。\n\n
\n\n
- 如果基础对象位于同一包中,则 ofs-delta 会对基础对象在包中的偏移量进行编码。
\n如果基础对象位于同一个包中,也可以进行 deltified。
\n\n
\n Ref-delta 还可以引用包外的对象(即\n 所谓的“瘦包”)。然而,当存储在磁盘上时,包应该是自包含的以避免循环依赖。增量数据是从基础对象重建对象的指令序列。
\n\n
\n 如果基础对象被德尔特化,则必须首先将其转换为规范形式。每条指令都会将越来越多的数据附加到目标对象,直到完成。
\n 目前支持两条指令:\n
\n\n- 一个用于从源对象复制字节范围,
\n- 一种用于插入嵌入指令本身的新数据。
\n每条指令的长度都是可变的。指令类型由第一个八位字节的第七位确定。下图遵循 RFC 1951(Deflate 压缩数据格式)中的约定。
\n
在 Git 2.20(2018 年第 4 季度)中,packstream 中格式错误或精心设计的数据可能会使我们的代码尝试读取或写入超过分配的缓冲区并中止,而不是报告错误,这一问题已得到修复。
\n\n\n\n\n\n\n
t5303
:用于printf
生成 Delta 基数增量基本文件的确切字节数非常重要。
\n\n
\ntest-delta
帮助器会将其提供给patch_delta()
,如果它与增量中给定的大小字节不匹配,它将抛出错误。
\n 在某些平台上使用“echo
”可能会出现意外的行结尾(例如,“\\r\\n
”而不仅仅是“\\n
”)。这实际上不会导致测试失败(因为我们已经期望 test-delta 会抱怨这些虚假的增量),但意味着我们没有执行我们认为的代码。
\n\n让我们使用
\nprintf
它(我们已经相信当我们生成增量时它会为我们提供字节完美的输出)。
在 Git 2.25(2020 年第一季度)中,在具有许多包文件的存储库中,通过使用低效的搜索算法来避免两次注册相同包文件的过程成本不必要地高,这一问题已得到纠正。
\n\n请参阅Colin Stolley的提交 ec48540(2019 年 11 月 27 日) ( )。\n (由Junio C Hamano 合并 -- --在提交 6d831b8中,2019 年 12 月 16 日)ccstolley
gitster
\n\n\n\n
packfile.c
:加快加载大量包文件的速度签署人:Colin Stolley
\n\n
\n 帮助人:Jeff King在启动时加载包文件时,我们会遍历每个文件一次的内部包文件列表,以避免重新加载已经加载的包文件。此检查以二次方的时间运行,因此对于维护不良且包含大量包文件的存储库来说,它可能会非常慢。
\n\n在加载包文件时添加包含包文件名称的哈希图,以便检查已加载包的平均运行时成本保持恒定。
\n\n向 p5303 添加性能测试以显示加速情况。
\n\n现有的 p5303 测试运行时间受其他因素支配,并未显示出明显的加速。
\n\n
\n p5303 中的新测试清楚地暴露了不良情况下的加速。
\n 在此测试中,我们创建 10,000 个包文件并测量 的启动时间git rev-parse
,除了加载包之外,它几乎没有其他作用。以下是新 p5303 测试的数据:
\n\nRun Code Online (Sandbox Code Playgroud)\n\nTest HEAD^ HEAD\n---------------------------------------------------------------------\n5303.12: load 10,000 packs 1.03(0.92+0.10) 0.12(0.02+0.09) -88.3%\n
\n
install_packed_git()
[jc:压制了peff调用 hashmap 的更改]
\n 签署人:Junio C Hamano
归档时间: |
|
查看次数: |
1779 次 |
最近记录: |