2、版本控制基础:Git核心概念(分支、合并、冲突解决),Git Flow与Trunk Based开发模式对比
2.1 分支:Git 的灵魂所在
说实话,我刚入行那会儿,对分支的理解特别肤浅。觉得分支不就是复制一份代码嘛,有啥好学的?直到有一次,我在一个项目里直接往 master 上 push 代码,结果把同事正在调试的功能给冲了……嗯,那次教训挺深刻的。
分支的本质,其实就是一个可移动的指针。每次你提交代码,这个指针就往前挪一步。我习惯把分支想象成「平行宇宙」——每个分支里都在发生不同的故事,但最终它们要合并回主时间线。
核心要点:
- 主分支(main/master):生产环境的代码,原则上不允许直接修改
- 功能分支(feature):开发新功能时创建,开发完合并回主分支
- 修复分支(hotfix):线上出 bug 时紧急创建,修完立刻合并
2.2 合并:把平行宇宙拉回正轨
合并说白了,就是把两个分支的改动拼到一起。Git 提供了两种合并方式,我分别说说我的使用感受。
2.2.1 Fast-Forward 合并
这种情况最理想。你想想看,如果主分支在你创建功能分支后一直没动过,那合并就只是把指针往前推一下,没有新提交产生。干净利落。
# 当前在 main 分支
git merge feature/login
# 如果 feature/login 是基于 main 的最新提交创建的
# Git 会直接移动 main 的指针到 feature/login 的位置
2.2.2 Three-Way 合并
大多数情况是这种。主分支和你自己的分支都做了修改,Git 需要找一个「共同祖先」,然后对比两边的差异,生成一个新的合并提交。
我的小建议:合并前先执行 git fetch 拉取最新代码,再用 git log --oneline --graph 看看分支拓扑图。我每次合并前都会看一眼这个图,心里就有底了。
2.3 冲突解决:Git 的「吵架」现场
冲突这东西,躲是躲不掉的。我记得有一次,我和另一个同事同时修改了同一个配置文件,结果合并时爆了 30 多个冲突……那天下午我啥也没干,就坐在那一个一个解。
冲突长什么样?Git 会在文件里插入这样的标记:
<<<<<<< HEAD
const API_URL = 'https://api.prod.com';
=======
const API_URL = 'https://api.dev.com';
>>>>>>> feature/debug
上面是当前分支的内容,下面是你要合并进来的内容。你需要手动决定保留哪个,或者两个都保留。
避坑指南:我曾经犯过一个低级错误——解完冲突后忘了删掉 <<<<<<< 和 ======= 这些标记,结果代码编译直接挂了。所以解完冲突后,一定要用 grep -r "<<<<<<" . 扫一遍项目,确保没有残留。
2.4 Git Flow vs Trunk Based:两种开发哲学的碰撞
这两种模式我都用过,各有各的适用场景。我直接拿表格对比一下,这样更直观。
| 对比维度 | Git Flow | Trunk Based |
|---|---|---|
| 分支数量 | 多(master、develop、feature、release、hotfix) | 少(主要就一个主分支) |
| 发布频率 | 低(通常按版本发布) | 高(每天多次甚至持续发布) |
| 冲突概率 | 低(分支隔离时间长) | 高(频繁合并,冲突多) |
| 适合团队 | 大型团队、传统项目 | 小型团队、敏捷团队 |
| 学习成本 | 高(分支模型复杂) | 低(简单直接) |
2.4.1 Git Flow:规矩多,但稳
Git Flow 是我最早接触的工作流。它把分支分得很细:develop 是日常开发分支,release 是预发布分支,hotfix 是紧急修复分支。每个分支都有明确的职责。
说实话,这种模式在管理大型项目时确实好用。我记得在做一个电商平台时,我们同时有 3 个版本在开发:v2.0 在测试,v2.1 在开发,v1.9 还在修 bug。Git Flow 的分支模型让这一切井井有条。
Git Flow 的典型流程:
- 从
develop创建feature/login - 开发完成后合并回
develop - 准备发布时,从
develop创建release/2.0 - 在
release分支上只修 bug,不加新功能 - 测试通过后,合并到
master和develop - 线上出 bug 时,从
master创建hotfix/2.0.1
2.4.2 Trunk Based:简单粗暴,但快
Trunk Based 就简单多了。所有开发者都在主分支上工作,或者最多创建短期存在的功能分支(通常不超过两天)。说白了,就是「频繁提交、频繁合并」。
我现在的团队就用 Trunk Based。每天每个人至少往主分支合并 2-3 次。刚开始大家都不适应,觉得太频繁了。但习惯了之后,你会发现冲突反而少了——因为每次合并的改动量都很小,解起来特别快。
我的经验:Trunk Based 要想玩得转,必须搭配特性开关(Feature Toggle)。比如你开发一个新功能,但还没做完,就用开关把它藏起来。这样即使代码合并到主分支,也不会影响线上用户。我见过太多团队因为不用特性开关,结果 Trunk Based 搞得一团糟。
2.5 到底选哪个?
这个问题没有标准答案。我个人的建议是:
- 如果你的团队超过 20 人,或者项目需要同时维护多个版本,Git Flow 更合适
- 如果你的团队在 10 人以内,追求快速迭代,Trunk Based 是更好的选择
- 如果你刚开始用 Git,先从 Trunk Based 入手,等熟练了再尝试 Git Flow
嗯,版本控制这东西,说白了就是「规矩」和「效率」的平衡。找到适合自己团队的节奏,比盲目追求某种「最佳实践」重要得多。