Git 里的 branch、merge、rebase 到底怎么理解

很多人把 Git 的日常提交流程跑顺之后,下一步最容易卡住的,就是这 3 个词:

  • branch
  • merge
  • rebase

它们看起来都和“合代码”有关,但又不像一回事。

于是新手很容易出现这种状态:

  • 知道分支很重要,但不敢开;
  • 知道 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分支
  • 后续的DE都是在这条新分支上发生的

这样做的好处是:

  • 主线保持稳定;
  • 你可以放心试错;
  • 多个人可以在不同分支上并行开发。

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上做了DE
  • 与此同时,主分支又继续往前走到了FG

如果你现在在feature上执行:

gitrebase main

它的意思可以理解成:

  • 先找到featuremain原来的分叉点;
  • 把你在feature上独有的提交拿出来;
  • 再把这些提交“重新接到”当前的main后面。

结果大致会变成:

main: A -> B -> C -> F -> G feature: D' -> E'

注意这里我写的是D'E',而不是原来的DE

这是因为:

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:为了把一条线的成果接回去,用 merge;
  • rebase:为了让自己的分支接上最新主线,或者整理历史,用 rebase。

如果你继续往前再压缩成一句话,就是:

branch 用来分开开发,merge 用来汇合历史,rebase 用来整理和重排历史。


十、结尾

很多人一开始会觉得 Git 难,往往不是因为命令本身,而是因为看不到项目历史其实是一张“时间图”。

只要你开始把 Git 理解成“多条历史线如何分开、如何汇合、如何整理”,那么:

  • branch就不再神秘;
  • merge就不只是一个命令;
  • rebase也不再像一个危险咒语。

下一篇我们继续讲:

Git 冲突和常见报错怎么处理

因为真正开始多人协作之后,最重要的不只是“会提交”,还要学会在出问题时知道该怎么稳稳地处理。