前置知识: Git

对象模型

3 minAdvanced2026/6/14

Git对象模型详解:blob、tree、commit、tag四种对象的结构与关系。

1. Git 对象概述

1.1 四种对象

Git 的核心是一个内容寻址文件系统,所有数据存储为四种对象:

对象作用存储内容
blob文件内容纯文件数据(无文件名)
tree目录结构文件名 + blob/tree 引用
commit提交快照tree 引用 + 父提交 + 元数据
tag标签指向 commit 的命名引用

1.2 对象关系

commit ──→ tree ──→ blob (文件内容)
  │           ├──→ blob (文件内容)
  │           ├──→ tree (子目录) ──→ blob
  │           │                  ──→ blob
  │           └──→ blob (文件内容)

  └──→ parent commit ──→ tree ──→ ...

2. Blob 对象

2.1 结构

Blob 存储文件的纯内容,不包含文件名和权限:

blob <size>\0<content>
# 创建 blob 对象
echo "hello world" | git hash-object -w --stdin
# 3b18e512dba79e4c8300dd08aeb37f8e728b8dad

# 查看 blob 内容
git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
# hello world

# 查看 blob 类型
git cat-file -t 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
# blob

2.2 去重机制

相同内容的文件共享同一个 blob:

# 两个文件内容相同
echo "hello" > a.txt
echo "hello" > b.txt

# 只创建一个 blob 对象
git add a.txt b.txt
git write-tree | xargs git ls-tree -r
# 100644 blob ce013625...    a.txt
# 100644 blob ce013625...    b.txt  ← 同一个 blob

3. Tree 对象

3.1 结构

Tree 存储目录结构,每个条目包含:

<mode> <type> <hash>\t<name>
# 查看 tree 对象
git cat-file -p HEAD^{tree}
# 100644 blob a1b2c3d4    README.md
# 100644 blob e5f6g7h8    index.js
# 040000 tree i9j0k1l2    src/

3.2 文件模式

模式说明
100644blob普通文件
100755blob可执行文件
040000tree目录
120000blob符号链接
160000commit模块

3.3 Tree 的嵌套

项目根 tree
├── 100644 blob abc123  README.md
├── 040000 tree def456  src/
│   ├── 100644 blob ghi789  index.ts
│   └── 040000 tree jkl012  utils/
│       └── 100644 blob mno345  helper.ts
└── 100644 blob pqr678  package.json

4. Commit 对象

4.1 结构

# 查看 commit 对象
git cat-file -p HEAD
# tree 9a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t
# parent a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0
# author Zhang San <zhang@example.com> 1718342400 +0800
# committer Zhang San <zhang@example.com> 1718342400 +0800
#
# feat: add user authentication

4.2 Commit 字段

字段说明
tree指向项目根目录的 tree 对象
parent指向父提交(合并提交有多个 parent)
author原始作者 + 时间戳
committer实际提交者 + 时间戳
message提交消息

4.3 提交链

commit C ← HEAD

  parent

commit B

  parent

commit A
# 查看提交链
git log --oneline --graph

# 查看合并提交的两个父提交
git cat-file -p <merge-commit-hash>
# parent <first-parent>
# parent <second-parent>

5. Tag 对象

5.1 轻量标签

轻量标签只是一个指向 commit 的引用,不创建对象:

git tag v1.0.0
# .git/refs/tags/v1.0.0 → commit hash

5.2 附注标签

附注标签创建一个独立的 tag 对象

git tag -a v1.0.0 -m "Release version 1.0.0"

# 查看 tag 对象
git cat-file -p v1.0.0
# object 9a1b2c3d...
# type commit
# tag v1.0.0
# tagger Zhang San <zhang@example.com> 1718342400 +0800
#
# Release version 1.0.0

5.3 标签字段

字段说明
object指向的 commit 对象
type对象型(通常是 commit)
tag标签名称
tagger打标签的人 + 时间戳
message标签消息

6. 对象存储机制

6.1 松散对象

新创建的对象以松散格式存储:

.git/objects/
├── 3b/
│   └── 18e512dba79e4c8300dd08aeb37f8e728b8dad
├── 9a/
│   └── 1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t
└── ...

路径 = 哈希前2位/哈希后38位

6.2 打包文件

git gc 将松散对象打包为包文件以节省空间:

# 手动打包
git gc

# 查看打包文件
ls .git/objects/pack/
# pack-xxxx.idx  pack-xxxx.pack

6.3 对象查询

# 查看对象类型
git cat-file -t <hash>

# 查看对象内容
git cat-file -p <hash>

# 查看对象大小
git cat-file -s <hash>

# 查看对象原始内容
git cat-file <hash> | zlib-decompress