跳转至

对象数据库

对象数据库是整个 Git 复现项目的根基。
如果这一层做不稳,后面所有命令都只是建立在不可靠存储之上的假动作。

最低要求是什么

一个 Git 风格对象数据库至少要能做到:

  • [type] [size]\x00[content] 编码对象;
  • 计算 SHA-1;
  • 按对象 ID 写入对象库路径;
  • 用 zlib 压缩 loose object;
  • 读出来时能解压、解析、校验;
  • 对损坏对象拒绝继续工作。

这不是“可选增强”,这是仓库可信度的底线。

为什么对象层必须先做扎实

因为后面的很多行为都只是对象层的组合:

  • add 先写 blob;
  • write-tree 组合 tree;
  • commit-tree 写 commit;
  • tag 可能写 tag 对象;
  • pack 只是另一种组织对象的方式;
  • fetch / push 只是在传输对象。

所以只要对象层出现这些问题:

  • header 算错;
  • size 不一致;
  • hash 不对应;
  • zlib 内容损坏;

整个系统都会跟着失真。

loose object 为什么适合教学

在项目早期,loose object 非常适合教学:

  • 路径结构直观;
  • 一对象一文件;
  • 易于检查;
  • 易于和官方 Git 做交叉验证。

这也是为什么很多 Git 复现项目先从 loose object 开始,而不是一上来就做 pack。

大文件为什么要流式处理

如果 hash-objectadd 遇到很大的文件,直接整文件读进内存不安全。
所以项目文档明确要求大文件使用分块读取,比如 64KB chunk。

这件事看起来像性能细节,实际上也是健壮性要求:

  • 避免内存暴涨;
  • 保持 hash 和压缩流程可流式推进;
  • 让实现更接近真实工具。

pack fallback 为什么重要

对象数据库不应该只会读 loose object。
一旦仓库里开始出现 pack / idx,读取逻辑就要支持:

  • 先查 loose object;
  • 没有时回退到 pack;
  • 通过 idx 做随机定位;
  • 必要时展开 delta。

这也是项目从“本地玩具系统”过渡到“具备分布式同步骨架”的关键一步。