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 应该关注什么?我总结了几点:

  1. 逻辑正确性:代码能不能跑?边界条件处理了吗?
  2. 可读性:变量命名是否清晰?有没有多余的注释?
  3. 安全性:有没有 SQL 注入?权限校验做了吗?
  4. 性能:有没有不必要的循环?数据库查询优化了吗?
  5. 测试覆盖:新代码有单元测试吗?

我个人习惯每次 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、及时解决冲突,你的团队就能从「天天吵架」变成「丝滑协作」。