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

【Git 内部】对象图:tree、commit、tag 的链式结构

文章导航

分类入口
opensource
标签入口
#git#git-internals#tree#commit#tag#object-graph

目录

松散对象的载荷不是孤立的——commit 指向一棵 tree,tree 条目指向 blob 或子 tree;tag 再指向 commit(或其它对象)。分支名 refs/heads/master 只是指向某个 commit ID 的别名。理解这条链,才能把「一次提交」翻译成磁盘上 3 个(或更多)松散文件。

本文用最小仓库的 git cat-file -p 实测输出,说明 tree/commit/tag 的文本格式与对象图拓扑。blob 编码见 松散对象


一、最小仓库的对象图

一次提交、单文件 hello.txt 时,对象库中有三个松散对象(尚未 repack):

commit 2b24b26a…  →  tree aaa96ced…  →  blob ce013625… (hello.txt)
对象图:ref 指向 commit,再经 tree 指向 blob

二、commit 对象

git cat-file -p HEAD(以下输出经删减,作者信息随环境变化):

tree aaa96ced2d9a1c8e72c56b253a0e2fe78393feb7
author … <…> 1783189662 +0800
committer … <…> 1783189662 +0800

init

字段含义(gitformat-commit):

commit 对象本身也是 blob 式存储:commit <size>\0 + 上述文本,再 zlib、SHA-1。


三、tree 对象

git cat-file -p aaa96ced2d9a1c8e72c56b253a0e2fe78393feb7

100644 blob ce013625030ba8dba906f756967f9e9ca394464a    hello.txt

每行:模式类型对象 ID文件名(显示时以制表符分隔;磁盘载荷在 NUL 前为二进制 SHA)。

常见模式:

mode 含义
100644 普通文件
100755 可执行文件
040000 子目录(条目类型为 tree
160000 gitlink(子模块,第 15 篇
120000 符号链接

子目录通过嵌套 tree 表达:父 tree 条目指向子 tree 的 SHA,子 tree 再列其条目。


四、多文件与多级目录

添加 src/a.txt 后,tree 可能变为:

100644 blob …   hello.txt
040000 tree …   src

子 tree src 内:

100644 blob …   a.txt

一次 git commit 若修改多个路径,会生成新的 tree 链(可能复用未变子 tree 的既有对象 ID),再生成新 commit。未变 blob 不会重复存储——内容寻址去重。


五、tag 对象

轻量标签refs/tags/v1.0 直接写 commit SHA,不创建 tag 对象。

附注标签(annotated tag):创建 tag 对象,载荷含 objecttypetagtagger、说明文字;refs/tags/v1.0 指向 tag 对象 ID。git pack-refs 可在 packed-refs^ 标记 peeled commit(第 04 篇)。


六、parent 链与合并

普通提交至多一个 parent 行。合并提交有两个 parent 行,分别指向合并前两个分支 tip。对象图从 DAG(有向无环图)变成「合并节点两入边」——仍无环,但拓扑更复杂。合并时 .git 临时文件见 第 13 篇


七、本文边界


参考资料

系列索引Git 内部结构 · 上篇松散对象 · 下篇refs 与 packed-refs

同主题继续阅读

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


By .