4、版本控制进阶:Git分支策略(Git Flow vs Trunk Based)、Code Review最佳实践、解决冲突的艺术
4.1 分支策略:选对路子,少走弯路
说到分支策略,我见过太多团队在这上面栽跟头了。有的团队一上来就搞 Git Flow,结果光分支就建了七八个,合并的时候乱成一锅粥。有的团队又太随意,所有人都在 master 上改,上线前谁都不敢合。
其实说白了,没有银弹。你得根据团队规模和发布节奏来选。我个人习惯把策略分成两大类:Git Flow 和 Trunk Based。
4.2 Git Flow:适合固定版本发布
Git Flow 是 2010 年 Vincent Driessen 提出的经典模型。它定义了五种分支:
- master:只存正式发布的代码
- develop:日常开发的主分支
- feature:每个新功能一个分支
- release:发布前的准备分支
- hotfix:紧急修复分支
我在项目中遇到过这样的情况:一个团队用 Git Flow 管理一个每两周发一版的 SaaS 产品。每次发版前,从 develop 拉一个 release 分支,只修 bug,不加新功能。等测试通过,合并到 master 并打 tag。嗯,这套流程对固定节奏的版本发布确实管用。
核心原则:master 永远是稳定的,develop 是集成的,feature 是隔离的。
但要注意,Git Flow 的缺点也很明显——分支太多。你想想看,一个小功能可能就改两行代码,却要经历 feature → develop → release → master 四轮合并。每次合并都可能出冲突,心累。
4.3 Trunk Based:适合持续交付
Trunk Based 就简单粗暴多了。所有开发都在主干(trunk 或 master)上进行,或者最多拉一个短期 feature 分支,生命周期不超过两天。
我建议如果你的团队在做微服务、或者每天要发版好几次,Trunk Based 是更好的选择。Google、Facebook 这些大厂内部都在用。
| 对比维度 | Git Flow | Trunk Based |
|---|---|---|
| 分支数量 | 多(5种以上) | 少(1-2种) |
| 合并频率 | 低(几天到几周) | 高(每天多次) |
| 适合场景 | 固定版本、大版本发布 | 持续交付、微服务 |
| 冲突风险 | 合并时集中爆发 | 分散、易解决 |
| 学习成本 | 高 | 低 |
我曾经在一个创业团队里推行 Trunk Based,刚开始大家都不习惯。有人觉得「直接在 master 上改?万一坏了怎么办?」后来我们加了一条铁律:每次提交必须通过 CI 和 Code Review。两周后,大家发现冲突少了,发布快了,也就接受了。
我的建议:团队少于 10 人、发布频繁的,选 Trunk Based。团队大、产品版本管理严格的,选 Git Flow。别纠结,先跑起来再说。
4.4 Code Review 最佳实践
Code Review 不是走过场。我见过最离谱的 CR,就是 reviewer 看了一眼说「LGTM」就过了,结果上线后出了大问题。
好的 CR 应该关注什么?我总结了几点:
- 逻辑正确性:代码能不能跑?边界条件处理了吗?
- 可读性:变量命名是否清晰?有没有多余的注释?
- 安全性:有没有 SQL 注入?权限校验做了吗?
- 性能:有没有不必要的循环?数据库查询优化了吗?
- 测试覆盖:新代码有单元测试吗?
我个人习惯每次 CR 不超过 200 行代码。超过 400 行的 PR,我直接打回去让作者拆分。为什么?因为人一次能有效 review 的代码量是有限的。你想想看,一个 1000 行的 PR,reviewer 看到后面早就忘了前面写了啥。
避坑指南:我曾经因为赶进度,review 了一个 800 行的 PR,只花了 10 分钟。结果上线后有一个空指针异常,排查了整整一天。从那以后,我坚持「小 PR、勤 review」的原则。
写 CR 评论也有技巧。别只说「这里不对」,要给出建议。比如:
// ❌ 不好的评论
// 这段代码效率低
// ✅ 好的评论
// 这个循环每次都会查询数据库,建议用批量查询替代。
// 可以参考 UserService.getUsersByIds() 方法。
4.5 解决冲突的艺术
冲突是 Git 里最让人头疼的事。但说白了,冲突的本质就是两个人改了同一段代码,Git 不知道听谁的。
我遇到过最经典的冲突场景:两个人同时改了同一个配置文件的同一行。一个人加了新功能配置,另一个人改了数据库连接。合并的时候,Git 直接罢工了。
解决冲突有几种策略:
- 手动合并:打开冲突文件,手动选择保留哪部分。适合小冲突。
- 使用合并工具:比如 Beyond Compare、Meld。可视化对比,效率高。
- rebase 代替 merge:rebase 会让提交历史更线性,冲突也更早暴露。
我个人更推荐 rebase。举个例子:
# 在 feature 分支上
git checkout feature/login
git rebase master
# 如果有冲突,Git 会停下来
# 解决冲突后
git add .
git rebase --continue
这样做的好处是,你的 feature 分支永远基于最新的 master,冲突在开发阶段就解决了,而不是等到合并时才发现。
小技巧:如果你不确定怎么解决冲突,先看看 Git 的冲突标记。<<<<<<< 和 ======= 之间是你的代码,======= 和 >>>>>>> 之间是别人的代码。理解了这一点,你就知道该保留哪部分了。
最后说一句:最好的解决冲突的方式,是避免冲突。怎么避免?多沟通、小提交、勤同步。你想想看,如果你每天 rebase 一次 master,冲突最多就是几行代码的事。如果你一个月才合并一次,那冲突可能几百行,神仙都救不了。
嗯,版本控制这件事,说到底是个习惯问题。选对策略、做好 review、及时解决冲突,你的团队就能从「天天吵架」变成「丝滑协作」。