Week 03: 分支模型与合并策略
深入理解 Git 分支的本质, 掌握各种合并策略与冲突解决机制.
1. 分支的本质
1.1 分支是什么
Git 分支只是一个指向 Commit 的可移动指针, 存储在 .git/refs/heads/ 目录中.
# 查看分支指向的 Commit
cat .git/refs/heads/main
# a1b2c3d4e5f6...
# 等价于
git rev-parse main分支操作的成本:
- 创建分支: 写入一个 41 字节的文件 (40 字符哈希 + 换行符)
- 切换分支: 更新 HEAD 和工作区
- 删除分支: 删除一个文件
1.2 HEAD 指针
HEAD 是一个特殊的引用, 指向当前分支:
cat .git/HEAD
# ref: refs/heads/main分离 HEAD 状态 (Detached HEAD): 当 checkout 到特定 Commit 而非分支时, HEAD 直接指向 Commit:
git checkout a1b2c3d
cat .git/HEAD
# a1b2c3d4e5f6...在分离 HEAD 状态下的提交不属于任何分支, 容易丢失.
1.3 分支命名约定
feature/ # 功能开发
bugfix/ # Bug 修复
hotfix/ # 紧急修复
release/ # 发布准备
experiment/ # 实验性功能2. 分支操作
2.1 基本操作
# 创建分支
git branch feature
# 创建并切换
git checkout -b feature
git switch -c feature # Git 2.23+
# 切换分支
git checkout main
git switch main # Git 2.23+
# 查看分支
git branch # 本地
git branch -r # 远程
git branch -a # 全部
git branch -v # 含最后提交
git branch --merged # 已合并到当前分支
# 删除分支
git branch -d feature # 安全删除 (已合并)
git branch -D feature # 强制删除
# 重命名分支
git branch -m old-name new-name2.2 分支与远程
# 推送分支
git push origin feature
# 建立跟踪关系
git push -u origin feature
git branch --set-upstream-to=origin/feature feature
# 删除远程分支
git push origin --delete feature3. 合并 (Merge)
3.1 合并类型
Fast-Forward 合并
当目标分支是当前分支的直接祖先时, Git 只需移动指针:
Before:
main: A---B
feature: \---C---D
After (git merge feature):
main: A---B---C---Dgit merge feature
# Fast-forward三方合并 (3-Way Merge)
当两个分支有分叉时, Git 创建一个合并提交:
Before:
main: A---B---E
feature: \---C---D
After (git merge feature):
main: A---B---E---F (merge commit)
\ /
feature: C---Dgit merge feature
# Merge made by the 'recursive' strategy.3.2 合并策略
Git 支持多种合并策略, 通过 -s 参数指定:
| 策略 | 说明 | 适用场景 |
|---|---|---|
recursive | 默认策略, 处理两个分支 | 常规合并 |
ort | Git 2.33+ 默认, 更快 | 常规合并 |
resolve | 传统策略, 较慢 | 简单合并 |
octopus | 合并多个分支 | 同时合并多分支 |
ours | 忽略对方所有更改 | 保留历史但不要内容 |
subtree | 合并到子目录 | 子项目合并 |
# 使用 ours 策略 (只保留当前分支内容)
git merge -s ours feature
# 合并多个分支 (octopus)
git merge feature1 feature2 feature33.3 合并选项
# 禁止 Fast-Forward (总是创建合并提交)
git merge --no-ff feature
# 只允许 Fast-Forward
git merge --ff-only feature
# 合并但不提交, 用于检查
git merge --no-commit feature
# 合并后压缩为一个提交
git merge --squash feature
git commit -m "Merge feature"4. 冲突解决
4.1 冲突标记
当同一文件的同一部分被两个分支修改时, 产生冲突:
<<<<<<< HEAD
当前分支的内容
=======
合并分支的内容
>>>>>>> feature4.2 解决冲突
# 1. 查看冲突文件
git status
# 2. 手动编辑解决冲突
vim conflict.txt
# 3. 标记为已解决
git add conflict.txt
# 4. 完成合并
git commit4.3 工具辅助
# 使用合并工具
git mergetool
# 常用工具配置
git config --global merge.tool vimdiff
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'4.4 冲突策略选项
# 自动选择某一方
git merge -X ours feature # 冲突时保留当前分支
git merge -X theirs feature # 冲突时保留合并分支
# 注意: -X 是策略选项, 不是策略
# -s ours 会忽略所有更改
# -X ours 只在冲突时选择当前分支4.5 Rerere (Reuse Recorded Resolution)
Rerere 记录冲突解决方案, 自动应用于相同冲突:
# 启用 Rerere
git config --global rerere.enabled true
# 查看记录
ls .git/rr-cache/
# 清除记录
git rerere forget conflict.txt工作原理:
- 第一次解决冲突时, Git 记录冲突内容和解决方案.
- 下次遇到相同冲突时, 自动应用解决方案.
5. 分支策略
5.1 Git Flow
经典的发布模型, 适合有计划发布周期的项目:
分支:
main: 生产环境代码develop: 开发主线feature/*: 功能开发release/*: 发布准备hotfix/*: 紧急修复
5.2 GitHub Flow
简化模型, 适合持续部署:
规则:
main分支始终可部署- 从
main创建功能分支 - 通过 Pull Request 合并
- 合并后立即部署
5.3 Trunk-Based Development
极简模型, 适合高频发布:
规则:
- 所有开发者直接提交到
main - 使用功能开关控制未完成功能
- 小批量、频繁提交
- 短生命周期分支 (< 1 天)
6. 高级分支操作
6.1 Worktree (多工作目录)
同时在多个分支工作, 无需切换:
# 创建 worktree
git worktree add ../feature-worktree feature
# 列出 worktree
git worktree list
# 删除 worktree
git worktree remove ../feature-worktree用途:
- 同时在多个分支开发
- 长时间构建时继续其他工作
- 比较不同分支的运行结果
6.2 分支比较
# 比较两个分支
git diff main..feature
git diff main...feature # 自共同祖先起
# 查看分支差异的提交
git log main..feature # feature 有而 main 没有的
git log main...feature # 两边各自独有的
# 查看共同祖先
git merge-base main feature7. 练习
7.1 合并策略实验
- 创建两个分支, 分别修改同一文件的不同部分, 合并.
- 创建冲突场景, 练习手动解决.
- 尝试
--squash合并.
7.2 Rerere 练习
- 启用 Rerere.
- 制造冲突并解决.
- 回退合并, 再次合并, 观察自动解决.
7.3 分支策略设计
为一个团队项目设计分支策略, 考虑:
- 发布频率
- 团队规模
- 环境数量
8. 思考题
- 为什么 Git 分支如此轻量?
--no-ff和--ff-only分别适合什么场景?-s ours和-X ours有什么区别?- Rerere 可能带来什么问题?
- 为什么 Trunk-Based 需要功能开关?
9. 本周小结
- 分支本质: 指向 Commit 的指针.
- HEAD: 指向当前分支或 Commit.
- 合并类型: Fast-Forward, 三方合并.
- 合并策略: recursive, ort, octopus, ours, subtree.
- 冲突解决: 手动编辑, 工具辅助, Rerere 自动化.
- 分支策略: Git Flow, GitHub Flow, Trunk-Based.
- Worktree: 多工作目录并行开发.
分支是 Git 最强大的特性之一. 理解其本质后, 分支操作就变成了指针的简单移动.