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

【Git 内部】松散对象:zlib 载荷与 SHA-1 路径

文章导航

分类入口
opensource
标签入口
#git#git-internals#loose-object#blob#sha1#zlib

目录

Git 对象库里的每个版本片段——文件内容、目录快照、提交元数据——都以松散对象(loose object)形式存放在 .git/objects/ 下,直到 git repack 把它们打进 pack。读不懂「对象头 + zlib + 以哈希命名路径」这三件事,就无法手工校验对象是否损坏,也看不懂 git fsck 报错里的 corrupt loose object

本文说明四种对象类型在未打包时的磁盘格式、SHA-1 对象 ID 的计算方式,以及路径 objects/ab/cdef… 的切分规则。对象之间的引用关系见 对象图


一、对象 ID 从哪来

对每个 Git 对象,先构造 ASCII 对象头

<type> <size>\0

再接上类型相关的载荷(payload)。对整个字节串做 SHA-1,得到 40 位十六进制对象 ID(SHA-256 仓库为 64 位,见 第 16 篇)。

松散对象写入管线:payload、对象头、SHA-1、zlib、磁盘路径

磁盘路径:取 ID 前 2 字符为目录名,剩余 38 字符为文件名:

.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a
对象 ID 切分为 objects/ab/cdef… 路径(SHA-1 示例)

文件内容是 zlib 压缩后的 header + payload,不是明文。


二、blob 实测:从文件到磁盘

工作区文件 hello.txt 内容为 hello\n(6 字节)。git hash-object hello.txt 输出:

ce013625030ba8dba906f756967f9e9ca394464a

git hash-object -w hello.txt 会写入上述路径。用 Python 解压验证(Git 2.54.0 实验仓库):

import zlib
raw = open(".git/objects/ce/013625030ba8dba906f756967f9e9ca394464a", "rb").read()
dec = zlib.decompress(raw)
# dec == b'blob 6\x00hello\n'
字段
压缩后大小 21 字节
解压后头 blob 6\0
载荷 hello\n

git cat-file -p ce013625… 只打印载荷部分 hello,与解压结果一致。

复现:

echo 'hello' > hello.txt
git hash-object hello.txt
git hash-object -w hello.txt
python3 -c "import zlib; print(zlib.decompress(open('.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a','rb').read()))"

(若内容不同,SHA 会变化;应以你本地的 git hash-object 输出为准。)


三、四种对象类型与载荷形状

类型 载荷概要
blob 原始文件字节
tree 多行 mode SP name NUL 20-byte-binary-SHA
commit tree …\nparent …\nauthor …\ncommitter …\n\nmessage
tag object …\ntype …\ntag …\ntagger …\n\nmessage(annotated tag)

类型名与空格、数字、NUL 构成头;载荷格式详见 gitformat-commit 等官方文档。

tree 与 commit 的文本展开示例见 第 03 篇


四、松散对象的权限与只读位

新写入的松散对象通常为 只读0444)。这是刻意设计:对象库内容不可变,防止误改。要做 fsck 损坏实验 时需 chmod u+w 再截断文件。


五、与 pack 的关系

松散对象是对象库的默认落盘形态;当数量或体积增长时,git repack 把多个对象合并进 .git/objects/pack/*.pack,并可能 prune 已被 pack 收录的松散文件(第 07第 10 篇)。对象 ID 不变——pack 只是另一种物理编码。


六、本文边界


参考资料

系列索引Git 内部结构 · 上篇.git 目录全景

同主题继续阅读

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


By .