据我了解,存储在[裸] git存储库中的松散对象已压缩...
......为什么git pack-objects
(以及所有相关的repack
和gc
命令)有一个很长的 Compressing objects
阶段?不应该只是复制它们吗?
例如:
objects/75/f0debd8e421ab3f9cc8b6aeb539796ae86b705
已被压缩。在打包文件中,应将此文件按字节顺序逐个复制到其标头之后的位置,因为打包文件格式指定了压缩后的数据就在那里了...那么,如果已经压缩过,为什么还需要重新压缩呢?
如果它可能正在尝试使用其他压缩方式...我怎么不告诉它,而是按原样使用文件?
更新的笔记:
.NEF
图像没有用。答案 0 :(得分:3)
据我了解,存储在[裸] git存储库中的松散对象已压缩...
是的。但是它们是 zlib-deflate 压缩的。
...那么为什么git pack-objects(以及所有相关的repack和gc命令)的压缩对象阶段真的很长?
无论如何,这些命令-git pack-objects
和git repack
; git gc
仅为您运行git repack
-将许多对象组合成一个 pack文件。
打包文件是压缩对象的不同方法。一个松散的对象是独立的:Git只需要读取该松散的对象并对其进行zlib充气传递,即可获取该对象的未压缩数据。相比之下,打包文件包含许多对象,其中一些对象首先是 delta压缩的。
Delta压缩的工作原理是:实际上,要生成该对象,请首先生成另一个对象。然后在此处添加这些字节和/或在此处删除N个字节。重复此添加和/或删除操作,直到我完成了增量列表为止。(然后,也可以对zata-defdef定义增量指令本身。)您可能会认为这是一种差异,实际上,某些非Git版本控制系统实际上使用diff或它们自己的内部diff引擎来生成其增量压缩文件。
传统上,这使用的观察是某些文件(例如foo.cc
或foo.py
)会通过在文件中的某些位置添加和/或删除几行而随时间变化,但会保留大容量一样。如果我们可以说:采用所有以前的版本,然后添加和/或删除这些行,则我们可以在比存储其中一个版本少的空间中存储两个版本。
我们当然可以在先前的增量压缩文件之上构建增量压缩文件:获得扩展先前的增量压缩文件并应用这些增量的结果。这些使< em> delta链,它可以根据您的喜好长久,也许可以一直回到最初创建文件的位置。
某些(非Git)系统在这里停止:每个文件都存储为对先前版本的更改,或者,每次存储文件时,系统都会存储最新文件,并翻阅先前的完整副本(是最新版本,因此是的完整副本)到将“最新”转换为“上一个”所需的增量中。第一种方法称为正向增量存储,而第二种方法当然是反向增量存储。正向增量通常具有一个严重的缺点,因为提取文件的最新版本需要提取第一个版本,然后应用很长的增量序列,这会花费很多时间。因此,RCS使用反向增量,这意味着获取最新版本的速度很快。它的版本很旧,速度很慢。 (但是,出于技术原因,这只能在RCS称为 trunk 上使用。RCS的“分支”改为使用正向增量。)Mercurial使用正向增量,但偶尔会存储文件的新完整副本,以便使δ链长度短。 SCCS是一种系统,它使用SCCS称为 interleaved delta 的技术,该技术为提取任何文件(但更难生成)提供了线性时间。
Git不会将文件存储为文件。您已经知道文件数据存储为
压缩所花费的大部分CPU时间都在于寻找良好的链。如果版本控制系统不能很好地选择文件(或对象),则压缩效果将不是很好。 Git使用了一堆试探法,包括窥探树对象以重建文件名(仅基础名,而不是完整路径名),因为否则时间复杂性会变得非常疯狂。但是,即使采用启发式方法,找到良好的增量链也很昂贵。通过“窗口”和“深度”设置,究竟可调价到底有多昂贵。
要详细了解打包文件,打包文件会随着时间的推移而进行多次修订,请参见Documentation/technical directory in Git。
答案 1 :(得分:0)
注意:关于--depth
argument of git pack-objects
,这在“torek”中由How to reduce the depth of an existing git clone?描述为:
delta 链的最大长度,当 Git 对存储在每个包文件中的 Git 对象使用其修改后的 xdelta 压缩时。
这与提交 DAG 特定部分的深度无关(根据每个分支头计算)。
因此,Git 2.32(2021 年第二季度)更加清晰:
"git pack-objects
"(man) 的选项采用 --window
和 --depth
等数值不应接受负值;输入验证已收紧。
参见commit 6d52b6a的commit 49ac1d3、commit 953aa54、commit 9535678、commit 5489899、Jeff King (peff
)(2021 年 5 月 1 日)。
(2021 年 5 月 11 日于 Junio C Hamano -- gitster
-- 被 commit 1af57f5 合并)
pack-objects
:将负深度限制为 0签字人:Jeff King
<块引用>负的 delta 深度没有意义,代码还没有准备好处理它。
如果在命令行上传递“--depth=-1
”,则来自 break_delta_chains()
的这一行:
cur->depth = (total_depth--) % (depth + 1);
触发除以零。
根据 C 标准,这是未定义的行为,但在 POSIX 系统上会导致 SIGFPE 终止进程。
这当然是通知用户命令无效的一种方式,但将其视为“不允许任何增量”会更友好一些,我们已经为 --depth=0
这样做了。