每个 blob、tree、commit 或 tag object 都分别对应 .git/objects 下的一个文件:

.git/objects/
└─ ab/
   └─ cdef123456...

取用 OID 的前两个十六进制字符用作目录名(例子中即 ab),其余字符作为文件名,避免objects 下单个目录包含过多文件。

文件中保存什么

Loose object 文件保存:

zlib(
  "<type> <content_length>\0" +
  content
)

与 pack 不同,loose object 文件包含 Git object header:

四种 loose object

类型 content
blob 文件内容
tree mode、文件名和子对象 OID
commit tree、parents、作者、时间和提交信息
tag 被标记对象、tagger 和 tag 信息

例如:

.git/objects/
├─ 12/345...  # blob
├─ 34/567...  # tree
├─ 56/789...  # commit
└─ 78/9ab...  # annotated tag

单看路径不能判断对象类型,必须解压并读取 header。

为什么先产生 loose object

执行:

git add

时,Git 通常会:

  1. 读取文件内容;
  2. 创建 blob;
  3. 计算 OID;