Packfile¶
当 Git 仓库对象很少时,使用 loose object 很直观。
每个对象就是对象库里一个单独压缩文件,容易理解,也容易调试。
但对象一多,问题就来了:
- 文件太碎;
- 文件系统负担变重;
- 网络传输不高效;
- 很多对象内容相似,却没有一起压缩。
这时就需要 packfile。
为什么需要 packfile¶
packfile 的目标主要有两个:
- 降低存储碎片和空间浪费
- 提高传输效率
Git 在本地做 gc、在远端做 fetch / push 时,都离不开 pack 的思路。
.pack 文件里是什么¶
一个 .pack 文件本质上是多个对象的二进制打包结果。
它通常包含:
- 文件头;
- 对象数量;
- 一系列对象实体;
- 可能的 delta 对象;
- 最终校验信息。
这样对象就不再是一个目录里无数零散小文件,而是被组织成一个更紧凑的二进制包。
为什么还需要 .idx¶
如果只有 .pack,想找某个对象时,你可能得把整包从头扫到尾。
这显然不高效。
所以 Git 还会配套一个 .idx 索引文件。它大致负责:
- 记录对象 ID 的有序列表;
- 提供 fan-out table;
- 提供对象偏移量;
- 让程序能更快地定位对象在
.pack中的位置。
简单理解就是:
.pack负责“装”.idx负责“找”
delta 对象为什么重要¶
很多对象之间其实非常像。
比如同一个大文本文件修改了几行,前后两个版本大部分内容都一样。
如果每次都完整存一份,会浪费很多空间。
因此 pack 里常会使用 delta 思路:
- 记录“基对象是什么”;
- 记录“在这个基对象基础上如何变成目标对象”。
这样传输和存储都能明显更省。
pack 和远端同步的关系¶
一旦谈到 clone、fetch、push,packfile 几乎就绕不过去。
因为远端同步的本质并不是“逐文件复制工作区”,而是:
- 找出缺失对象;
- 把这些对象组织成可传输的包;
- 对方接收后写入对象库并更新 refs。
所以 pack 是 Git 分布式能力的重要基础设施。
在 python-git-reproduction 中的意义¶
这个项目已经实现了:
- pack v2 基础读取;
- idx v2 基础读取;
- 包内对象随机寻址;
- ref-delta 解析;
- 非 delta pack 生成;
- 本地路径远端和
.pygit服务端同步。
也就是说,这个项目已经不是只会玩 loose object 的小练习了,而是开始触及 Git 分布式同步的真正骨架。