Git 里的 branch、merge、rebase 到底怎么理解
很多人把 Git 的日常提交流程跑顺之后下一步最容易卡住的就是这 3 个词branchmergerebase它们看起来都和“合代码”有关但又不像一回事。于是新手很容易出现这种状态知道分支很重要但不敢开知道 merge 能合并但不知道它和 rebase 差在哪看到别人说“别乱 rebase”就更不敢碰了。其实这 3 个概念并没有那么神秘。如果只用一句话先概括它们branch开一条独立开发线merge把两条开发线合到一起rebase把一条开发线“换个起点重新排一下”。这篇文章就专门把这 3 件事拆清楚。一、为什么需要 branch如果一个项目只有一条主线所有人都直接在主分支上改代码那么很快就会出现很多问题你想试一个新功能但怕把主线改坏两个人同时开发不同功能修改彼此干扰某个实验还没完成但主线又需要保持稳定。所以 Git 给出的解决办法是不要所有改动都挤在同一条线上而是先开分支。二、branch 到底是什么你可以把branch理解成项目历史中的一条并行开发线。最常见的主分支通常叫main或者master如果你现在要做一个新功能、新实验、新 bug 修复就完全可以从主分支上再开出一条新线在那上面单独开发。比如main: A - B - C feature: D - E这里的意思是主分支先走到了C你从C这个位置开了一个feature分支后续的D、E都是在这条新分支上发生的这样做的好处是主线保持稳定你可以放心试错多个人可以在不同分支上并行开发。1. 最常用的分支命令查看当前有哪些分支gitbranch创建并切换到新分支gitswitch-cfeature-login如果你的 Git 版本较老也可能看到这种写法gitcheckout-bfeature-login切回主分支gitswitch main三、merge 是什么当你在分支上把功能做完了接下来通常会遇到一个问题我怎么把这条分支的成果带回主分支这时候就轮到merge了。1. merge 的本质merge的本质是把两条分支的历史汇合起来。比如main: A - B - C feature: D - E当你回到main执行gitmerge feature结果大致可以理解成main: A - B - C ------ M \ / feature: D - E这里的M可以理解成一个“合并点”。它表示main原来有自己的历史feature也有自己的历史现在这两条历史被合到一起了。2. merge 的优点merge最大的优点是它会比较忠实地保留协作过程。也就是说你以后回头看会更容易知道这个功能是在哪条分支上做的什么时候被合并回主线这段历史原本是并行发展的。所以如果你比较看重真实协作痕迹merge会很自然。四、rebase 是什么如果说merge是“把两条线接到一起”那么rebase更像是把你这条分支上的提交重新放到另一个新的起点上。这句话第一次看会有点绕我们用图来理解。假设现在是这样main: A - B - C - F - G feature: D - E也就是说你从C开了feature你在feature上做了D、E与此同时主分支又继续往前走到了F、G如果你现在在feature上执行gitrebase main它的意思可以理解成先找到feature和main原来的分叉点把你在feature上独有的提交拿出来再把这些提交“重新接到”当前的main后面。结果大致会变成main: A - B - C - F - G feature: D - E注意这里我写的是D、E而不是原来的D、E。这是因为rebase 不是简单挪位置而是把这些提交在新起点上重新播放了一遍。所以从 Git 的角度看它们已经是“新的提交”了。1. rebase 的优点rebase最大的优点是历史会更线性、更整洁。你回头看日志时不会看到很多交叉出来再 merge 回去的结构而更像一条连续主线。这也是为什么很多团队会喜欢在个人分支上用 rebase 来整理历史。五、merge 和 rebase 到底有什么区别如果只抓最核心的差别可以记这几条。1. merge 更像“保留真实协作历史”它承认大家确实在不同分支并行开发过这些分支后来被合并了历史里应该看得见这件事。所以merge更强调真实过程2. rebase 更像“整理历史让它更线性”它不太强调原本历史分叉得有多复杂而是更关注最终日志是否清楚提交顺序是否更直阅读历史时是否更干净。所以rebase更强调整理结果3. merge 往往会保留一个合并痕迹而 rebase 通常不会产生那种显式的合并节点它更像把你的提交重新排了一下。六、什么时候用 branch、什么时候 merge、什么时候 rebase这其实是新手最想知道的部分。1. 什么时候开 branch只要你准备做下面这些事情都很适合先开分支开发一个新功能修一个 bug尝试一个实验思路改一个可能比较大的重构。一句话就是只要改动值得被单独管理就很适合开分支。2. 什么时候用 merge如果你希望保留更真实的协作历史清楚看到某个功能分支是什么时候并入主线的团队里大家都更习惯“分支开发 合并回主线”的方式那就优先用merge。对于很多团队协作场景merge都是很自然也很稳妥的选择。3. 什么时候用 rebase如果你希望在把分支合回去之前先把自己的分支历史整理得更干净让自己的分支跟上最新的主分支让提交历史更线性、更容易阅读那就可以考虑rebase。比较典型的场景是你在个人分支上开发了一段时间主分支已经有了新进展你想先把自己的分支更新到最新主线再继续工作或再提交合并。七、为什么很多人说“不要乱 rebase”这句话不是说rebase不好而是说rebase 会改写提交历史。这意味着如果这条分支已经被别人基于它继续开发或者已经作为共享历史被大家依赖那你再去 rebase就可能把别人原来对齐的历史打乱。所以一个很常见、也很稳的经验是个人分支上可以谨慎用 rebase已经共享给多人使用的公共分支上不要随便改写历史。你可以先把它理解成merge更保守rebase更讲究整理但整理历史这件事要建立在你知道这段历史是不是已经被别人依赖的前提上。八、一个最常见的实际场景假设你要开发一个登录功能。第一步从主分支开分支gitswitch maingitswitch-cfeature-login第二步在分支上开发并提交gitadd.gitcommit-m新增登录表单第三步主分支这时也有别人提交了新内容这意味着你的分支和主分支已经分开发展了一段时间。第四步你有两种常见处理方式方式一直接合并主分支变化在自己的分支上gitmerge main或者最后切回主分支再gitswitch maingitmerge feature-login方式二先把自己的分支 rebase 到最新主分支上gitswitch feature-logingitrebase main然后再回到主分支合并。这两种方式都可能合理关键是你想保留哪种历史形态以及团队平时采用什么习惯。九、新手可以先记住的最简判断如果你暂时还不想把这件事想得特别复杂可以先记住下面这套非常实用的判断branch为了把改动和主线分开先开一条线merge为了把一条线的成果接回去用 mergerebase为了让自己的分支接上最新主线或者整理历史用 rebase。如果你继续往前再压缩成一句话就是branch 用来分开开发merge 用来汇合历史rebase 用来整理和重排历史。十、结尾很多人一开始会觉得 Git 难往往不是因为命令本身而是因为看不到项目历史其实是一张“时间图”。只要你开始把 Git 理解成“多条历史线如何分开、如何汇合、如何整理”那么branch就不再神秘merge就不只是一个命令rebase也不再像一个危险咒语。下一篇我们继续讲Git 冲突和常见报错怎么处理因为真正开始多人协作之后最重要的不只是“会提交”还要学会在出问题时知道该怎么稳稳地处理。