这一篇在干嘛?

分支模型被称为 Git 的「必杀技」:创建分支是瞬间的,切换是秒级的,这与复制整个项目目录的老式 VCS 天壤之别。搞懂它你才算真正会用 Git。对应《Pro Git》第 3 章前半部分。

分支的本质:一个 41 字节的文件

先回顾提交的结构:每次提交生成一个提交对象,包含指向内容快照的指针、作者信息、说明,以及指向父提交的指针。提交串成链,就是历史。

Git 的分支,本质上只是一个指向某条提交的可变指针——实际就是 .git/refs/heads/ 下的一个小文件,里面写着一个 40 位的哈希加换行,共 41 字节。创建分支 = 写一个 41 字节的文件,所以「瞬间完成」毫不夸张。

main(或 master)也不是什么特殊分支,只是 git init 默认创建的第一个分支,和其他分支完全平等。

HEAD:你在哪,它指哪

Git 怎么知道你当前在哪个分支?靠一个特殊指针 HEAD,它指向当前所在的本地分支(再由分支指向具体提交)。

        ┌────────┐      ┌────────┐
        │ testing │───┐  │  main  │──┐
        └────────┘   │  └────────┘  │
                     ▼              ▼
                  commit C2 ◀───── 共同历史 C1

关键三连:

git branch testing        # 创建分支(只建指针,不切换!HEAD 仍在 main)
git checkout testing      # 切换过去(HEAD 指向 testing)
git checkout -b newfeat   # 创建并切换,一步到位(最常用)

切换分支时工作目录的文件会被改变成目标分支的快照内容——切到旧分支,你看到的就是旧版本。若当前有未提交的修改导致无法干净切换,Git 会拒绝并提示。

理解了「分支=指针、HEAD=你在哪」,两分支各自提交后会自然分叉,git log --oneline --graph --all 一眼看清。

合并:快进与三方合并

main 上把 feature 的成果收回来:

git checkout main
git merge feature

情况一:快进(fast-forward)

如果 main 自分叉后没有新提交,合并就是简单地把 main 指针向前挪到 feature 的最新提交——「快进」,不产生新提交。

情况二:三方合并

如果两个分支都有各自的新提交,Git 会找到它们的共同祖先,把「祖先、你这边最新、对方最新」三方快照做合并,生成一个有两条父指针的合并提交

冲突:两边改了同一处

两个分支改了同一个文件的同一区域,Git 无法替你决定,会报 CONFLICT (content): Merge conflict in xxx,把该文件标记为冲突状态。打开文件会看到:

<<<<<<< HEAD
你这边的版本
=======
对方分支的版本
>>>>>>> feature

解决三步:

  1. 手动编辑文件,留下想要的最终内容(可以两边都要、可以重写),删掉 <<<<<<</=======/>>>>>>> 标记
  2. git add <冲突文件> 标记「已解决」。
  3. git commit 完成合并提交。

中途想放弃:git merge --abort 回到合并前的状态。工具党可用 git mergetool 打开图形化冲突编辑器。

分支管理常用命令

git branch                 # 列出本地分支(* 标记当前所在)
git branch -v              # 附带每个分支最新提交
git branch --merged        # 已合并进当前分支的(可安全删除)
git branch --no-merged     # 还有未合并工作的
git branch -d feature      # 删除已合并的分支(只是删指针,提交仍在)
git branch -D feature      # 强制删除未合并的分支(工作会真的丢失)

分支开发工作流

因为建分支几乎零成本,Git 鼓励长期保持 main 稳定可用,所有开发都在主题分支上进行,完成后再合并回去。常见套路:

  • 长期分支main 只放稳定代码,develop 承接日常开发,成熟后从 develop 合入 main。
  • 主题分支(feature branch):每个功能/每个 bug 一个短命分支,改完即合并删除。分支名用 feature-loginfix-header-crash 这类自解释命名。

核心思想:分支是廉价且一次性的,main 是唯一需要长期保持干净的东西

小结

  • 分支 = 指向提交的 41 字节指针文件;main 毫不特殊。
  • HEAD 指向当前分支;git checkout -b 建分支并切换。
  • 合并两形态:快进(一边没新提交)与三方合并(生成合并提交)。
  • 冲突三步:改文件去掉标记 → add → commit;慌了就 --abort
  • 工作流:main 保稳定,一切开发走主题分支。

学完你会得到:

  • 「分支只是指针」这个让一切变简单的心智模型
  • branch / checkout -b / merge / 冲突处理的完整实操
  • 一套直接可用的主题分支工作流

自测

下一篇:🚀 远程分支与变基