土法炼钢兴趣小组的算法知识备份

【Git 内部】pack 与 idx 文件格式

文章导航

分类入口
opensource
标签入口
#git#git-internals#packfile#idx#verify-pack

目录

松散对象适合少量写入;历史一长,.git/objects/ 下成千上万个小文件会带来 inode 与目录压力(参见 小文件问题)。packfile 把多个对象串进单个 .pack,用 .idx 按 SHA 查偏移。传输 fetch/push 时传的也是 pack(第 14 篇)。

本文依据 gitformat-pack 说明 pack/idx 布局,并用 git verify-pack -v 解读实测输出。


一、文件对

文件 作用
objects/pack/pack-<hash>.pack 连续存放的对象数据 + pack 尾部校验
objects/pack/pack-<hash>.idx 按对象 SHA 排序的索引,指向 pack 内偏移
objects/info/packs 列出仓库使用的 pack 文件
*.rev(可选) reverse index,加速 reachability(较新版本)

pack 文件名中的 hash 为 pack 文件内容的 SHA-1(不含 idx)。


二、pack 文件结构(概念)

pack 与 idx 文件布局:PACK 头、对象序列、尾部校验与 idx 偏移表
  1. 头部:签名 PACK、版本(通常为 2)、对象个数。
  2. 对象序列:每个对象带类型与长度编码,后跟 zlib 压缩数据或 delta 指令。
  3. 尾部:整个 pack 的 SHA-1 校验和。

对象类型(3 bit 分类,见官方文档):

类型 含义
commit / tree / blob / tag 与松散对象相同语义
OFS_DELTA 以 pack 内负偏移引用基对象
REF_DELTA 以 20 字节 SHA 引用基对象

三、verify-pack 实测

对仅含一次提交的小仓库执行 git repack -ad 后:

git verify-pack -v .git/objects/pack/*.pack

输出(以下经删减):

2b24b26a117ef5cfdbf88040e282ec86085e6b1f commit 228 145 12
ce013625030ba8dba906f756967f9e9ca394464a blob   6 15 157
aaa96ced2d9a1c8e72c56b253a0e2fe78393feb7 tree   37 48 172
non delta: 3 objects

列含义:SHA type uncompressed-size compressed-size offset-in-pack。三者均为 non delta——小仓库无相似对象可链。

git count-objects -v 同期:

in-pack: 3
packs: 1
size-pack: 1

松散对象计数为 0 表示已全部进 pack(若未 prune 可能仍有冗余松散文件,见 第 10 篇)。


四、idx v2 概要

idx 使 git cat-file 能在 pack 内 O(log N) 定位对象:

读取对象时:SHA → idx 查 offset → pack 解压。REF_DELTA 需再解析基对象(可能在同一 pack 内更早偏移)。

idx 查对象:SHA 经 fanout 与二分定位 pack 内偏移

五、与松散对象的语义等价

pack 是物理编码;对象 ID 仍是对「头+载荷」的哈希,与松散存储一致。git cat-file -p <sha> 无需关心对象来自松散还是 pack。


六、本文边界


参考资料

系列索引Git 内部结构 · 上篇index · 下篇pack-objects 与 delta

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-07-05 · opensource

【Git 内部】Git 内部结构:对象库与磁盘文件格式

从 .git 目录布局、松散对象与 packfile 格式,到 refs、index、reflog、gc/fsck 与 fetch/push 落地——用官方 format 文档与本地实测 dump 系统讲清 Git 把版本历史存在哪、每个命令改写了哪些文件。全 16 篇。


By .