git - 如果对象已经被压缩,为什么 git pack-objects 会“压缩对象”?
问题描述
据我了解,存储在 [bare] git 存储库中的松散对象已被压缩......
...那么为什么git pack-objects
(以及所有相关的repack
命令gc
)有一个很长的 Compressing objects
阶段?不应该只是抄袭吗?
例如:
objects/75/f0debd8e421ab3f9cc8b6aeb539796ae86b705
已经被压缩了。在包文件中,这个文件应该在它的头部之后立即按字节复制到该位置,因为包文件格式指定压缩数据到那里......那么,如果它已经被压缩了,为什么还需要重新压缩呢?
如果它可能试图使用不同的压缩......我怎么能告诉它不要,而只是按原样使用文件?
更新说明:
- 我已经设置了设置和选项,使得增量压缩不会有效地发生。Delta 压缩不适用于存储 2 TB 的
.NEF
图像。
解决方案
据我了解,存储在 [bare] git 存储库中的松散对象已被压缩......
他们是。但它们是zlib-deflate压缩的。
...那么为什么 git pack-objects (以及所有相关的 repack 和 gc 命令)有一个非常长的 Compressing objects 阶段?
这些命令——<code>git pack-objects 和git repack
,无论如何;git gc
只git repack
为你运行——将许多对象组合到一个包文件中。
包文件是压缩对象的另一种方式。松散对象是独立的:Git 只需要读取松散对象并在其上运行 zlib 膨胀传递即可获取该对象的未压缩数据。相比之下,一个包文件包含许多对象,其中一些对象首先是delta-compressed。
Delta 压缩实际上是这样说的:要产生这个对象,首先要产生另一个对象。然后在此处添加这些字节和/或在此处删除 N 个字节。重复此添加和/或删除操作,直到完成增量列表。 (delta 指令本身也可以被 zlib-deflate。)你可能会认为这是一种 diff,事实上,一些非 Git 版本控制系统确实使用 diff 或它们自己的内部 diff 引擎来生成它们的增量压缩文件。
传统上,这使用观察到某些文件(例如,foo.cc
或foo.py
)倾向于通过在文件中的某处添加和/或删除几行而随时间变化,但保持大部分相同。如果我们可以说:获取所有以前的版本,然后添加和/或删除这些行,我们可以将两个版本存储在比存储其中一个版本要少得多的空间中。
当然,我们可以在之前的 delta 压缩文件之上构建一个 delta 压缩文件:获取扩展之前的 delta 压缩文件的结果,并应用这些 delta。 这些构成了delta 链,可以任意长,也许可以一直追溯到第一次创建文件的位置。
一些(非 Git)系统停在这里:每个文件都存储为对先前版本的更改,或者,每次存储文件时,系统都会存储最新的,并转换先前的完整副本(以前是最新的,因此是完整的副本)到将“最新”转换为“以前”所需的增量中。第一种方法称为正向增量存储,而第二种方法当然是反向增量存储。前向增量往往处于一个可怕的劣势,因为它提取了最新的文件的版本需要提取第一个版本,然后应用很长的增量序列,这需要很长时间。因此,RCS 使用反向增量,这意味着获取最新版本很快;它得到了一个非常旧的版本,速度很慢。(但是,出于技术原因,这只适用于 RCS 所谓的主干。RCS 的“分支”使用正向增量。) Mercurial 使用正向增量,但偶尔会存储文件的新完整副本,以保持增量链长度短。一个系统 SCCS 使用一种 SCCS 称为interleaved deltas的技术,该技术为提取任何文件提供了线性时间(但更难生成)。
但是,Git 不会将文件存储为files。您已经知道文件数据存储为blob 对象,它最初只是 zlib-deflate,否则是完整的。给定一组对象,其中一些是文件数据,而另一些不是(提交、树或带注释的标记对象),哪些数据属于哪个文件完全不明显。因此,Git 所做的就是找到一个可能的候选对象:某个对象似乎与其他对象有很多相似之处,最好的表达方式可能是从另一个对象开始,然后进行这些增量更改。
压缩中花费的大部分 CPU 时间都花在寻找好的链上。如果版本控制系统选择文件(或对象)不佳,则压缩效果不会很好。Git 使用了一堆启发式方法,包括窥视树对象以重建文件名(仅基本名称 - 不是完整路径名),否则时间复杂度会变得非常疯狂。但即使使用启发式方法,找到好的三角链也是昂贵的。通过“窗口”和“深度”设置,究竟有多昂贵是可调的。
有关(更多)关于打包文件的信息,这些文件随着时间的推移经历了多次修订,请参阅Git 中的 Documentation/technical 目录。
推荐阅读
- reactjs - React - 表格的无限滚动
- android - Android和iOS上的图片大小差异问题
- python - 是否有可能在数据之后创建 ylim 只显示数字?
- javascript - API 调用需要很长时间(数据集 250.000 条记录)
- django - 如何使用 slug 通过多对多类“objects.filter”检索数据
- blockchain - 不能使用后备。什么都没发生!函数()外部应付{}
- android - 我应该将 cityName 添加到具有 4 个片段的导航组件中的 Bundle 多少次?
- api - 用于图像上传的 Rest Assured multipart/Form-Data 中的 API 出现错误,因为上传的图像不是 jpg/jpeg 或 png 类型“
- apache-spark - Spark 虽然分区号为 1 却生成了很多任务 Pyspark
- python - pybind11 内存泄漏和崩溃