Skip to content

Merge vs Rebase

在 Git 中,mergerebase 是合并分支的两种主要方式。它们的目的相同:将一个分支的更改集成到另一个分支,但实现方式和最终的历史记录截然不同。

1. Git Merge (合并)

merge 是最常见的合并方式。它保留了分支的原始历史,并创建一个新的“合并提交” (Merge Commit)。

工作原理

假设你有 main 分支和 feature 分支:

bash
git checkout main
git merge feature

Git 会做两件事:

  1. 找到两个分支的最近共同祖先。
  2. feature 分支自祖先以来的所有更改,合并到 main 分支。
  3. 创建一个新的 Commit(称为 Merge Commit),它有两个父节点。

图解

text
      A---B---C feature
     /         \
D---E---F-------G main (Merge Commit)

优缺点

  • 优点
    • 非破坏性:完全保留了历史记录,不会修改现有的 Commit。
    • 真实性:忠实地记录了开发的实际发生顺序。
    • 简单:操作简单,冲突处理相对直观。
  • 缺点
    • 历史混乱:如果分支很多,历史记录会变成复杂的网状结构("Spaghetti History"),难以阅读。
    • 噪音:产生大量的 Merge Commit,可能掩盖了实际的代码更改。

2. Git Rebase (变基)

rebase 的意思是“改变基础”。它将当前分支的更改,“重新播放”在目标分支的最新提交之上。

工作原理

bash
git checkout feature
git rebase main

Git 会做以下操作:

  1. 找到 featuremain 的共同祖先。
  2. 暂时保存 feature 分支上的所有更改(Commits)。
  3. feature 分支指向 main 的最新提交。
  4. 将保存的更改逐个应用到新的基础之上(可能会产生新的 Hash)。

图解

Rebase 前:

text
      A---B feature
     /
D---E---F main

Rebase 后:

text
          A'--B' feature
         /
D---E---F main

最终看起来就像是 feature 分支是直接从 main 的最新提交 F 开始开发的,历史变成了一条直线。

优缺点

  • 优点
    • 线性历史:历史记录非常干净、整洁,像一条直线。
    • 易于追踪:没有多余的 Merge Commit,git log 更清晰。
  • 缺点
    • 修改历史:它会改变 Commit 的 Hash 值。
    • 风险:如果分支已经推送到公共仓库,Rebase 会导致其他人的历史混乱。
    • 冲突处理:如果在多个 Commit 中有冲突,可能需要多次解决冲突(每个 Commit 应用时都可能冲突)。

3. 黄金法则 (Golden Rule)

绝不要在公共分支(如 main)上使用 Rebase!

只在你自己的私有分支(尚未推送到远程,或只有你一个人使用的分支)上使用 Rebase 来整理提交。

4. 总结对比

特性Git MergeGit Rebase
历史形态网状结构,保留分支轨迹线性结构,单一直线
Merge Commit有 (除非是 Fast-forward)
Commit Hash不变改变 (即便是相同内容的提交)
冲突处理一次性解决可能需要分多次解决
适用场景公共分支合并,保留完整历史个人分支整理,追求整洁历史

什么时候用哪个?

  • 使用 Merge:当你想要记录“这里发生了一次合并”时,或者在公共分支上工作时。
  • 使用 Rebase:当你想要清理本地提交历史,或者想要将你的功能分支更新到最新的 main 代码以便后续合并时(通常是 git pull --rebase)。