前面我们已经把 对象模型 (blob / tree / commit / tag) 打好了地基,现在进入 分支 (branch) ,就会非常自然了。
分支的本质
-
在 Git 里,分支 = 一个可变的引用(reference) 。
-
它的工作就是 指向某个 commit 哈希。
-
文件位置:
.git/refs/heads/<分支名>
- 文件内容就是一个 commit 的哈希值。
例子:
bash
.git/refs/heads/master → cC1234...
表示 master
分支指向 commit cC1234...
。
分支和 HEAD 的关系
- HEAD:特殊引用,表示"你当前检出的分支"。
- HEAD 本身也只是一个引用,它通常指向某个分支:
bash
HEAD → refs/heads/master
-
当你在 master 分支提交一次:
- Git 新建一个 commit
cD
,父指针 =cC
。 - 更新
refs/heads/master
,让它从cC
移动到cD
。 - HEAD 也就随之"看到"新的提交。
- Git 新建一个 commit
👉 所以 分支是"可变的指针",HEAD 是"你正在操作的那个指针" 。
checkout branch 的本质
当你 git checkout dev
时:
- Git 让
HEAD
指向refs/heads/dev
。 - 然后把
dev
当前指向的 commit 的快照,解压到工作区和暂存区。
👉 所以切换分支不是"切换代码",而是"切换 HEAD 指向的 commit,再把快照恢复出来"。
merge 的本质
假设:
makefile
master: A → B → C (HEAD)
dev: A → D
-
当你在 master 上执行
git merge dev
:- Git 发现两个分支的提交历史有分叉。
- 它会找到共同祖先 A。
- 进行"三方合并":比较 A、C、D 的内容,生成新 commit
M
。 - 更新 master 指针 → M。
结果:
less
master(dev合并后): A → B → C → M
dev: A → D ──┘
👉 merge 本质:创建一个新的 commit,它有两个父指针。
小对比:branch / tag / HEAD
- branch:可变指针 → 随提交前进。
- tag:不可变引用 → 永远固定在某个 commit。
- HEAD:当前正在操作的引用 → 通常指向某个 branch。