DevToolBox免费
博客

Git Rebase vs Merge:何时使用哪个(图解对比)

10 分钟阅读作者 DevToolBox

rebase 和 merge 的争论是 Git 工作流中最常见的讨论之一。两个命令都将一个分支的更改整合到另一个分支,但方式完全不同。理解何时使用哪个对于维护清晰、可导航的项目历史至关重要。

Git Merge 工作原理

Git merge 创建一个新的"合并提交"来连接两个分支的历史。它保留了完整的历史记录和提交的时间顺序。

当你运行 git merge feature 时,Git 找到两个分支的公共祖先,然后创建一个新的提交来合并两者的更改。

          A---B---C  feature
         /         \
    D---E---F---G---H  main (merge commit)

$ git checkout main
$ git merge feature

Git Rebase 工作原理

Git rebase 将你的提交移动(或"重放")到另一个分支的顶部。它重写提交历史以创建线性的提交序列。

当你在功能分支上运行 git rebase main 时,Git 取出你分支中的每个提交,临时移除它们,将分支更新到 main 的最新状态,然后逐个在顶部重新应用每个提交。

Before rebase:
          A---B---C  feature
         /
    D---E---F---G  main

After rebase:
                    A'--B'--C'  feature
                   /
    D---E---F---G  main

$ git checkout feature
$ git rebase main

可视化对比

╔═══════════════════════════════════════════╗
║              MERGE RESULT                 ║
║                                           ║
║    D---E---F---G---H  main                ║
║         \       /                          ║
║          A---B---C  feature               ║
║                                           ║
║  ✓ Preserves all commits                  ║
║  ✓ Shows merge point                      ║
║  ✗ Non-linear history                     ║
╚═══════════════════════════════════════════╝

╔═══════════════════════════════════════════╗
║              REBASE RESULT                ║
║                                           ║
║    D---E---F---G---A'--B'--C'  main       ║
║                                           ║
║  ✓ Clean linear history                   ║
║  ✓ Easy to read                           ║
║  ✗ Rewrites commit hashes                 ║
╚═══════════════════════════════════════════╝

何时使用 Merge

  • 公共/共享分支——Merge 不会重写历史,对其他人正在使用的分支是安全的。
  • 保留上下文——合并提交显示了功能分支何时以及由谁整合。
  • 团队协作——多人在同一分支工作时,merge 避免了历史重写导致的冲突。
  • 发布分支——合并发布分支保留了确切的整合点。
# Merge with merge commit (recommended for main)
$ git checkout main
$ git merge --no-ff feature
$ git push origin main

何时使用 Rebase

  • 功能分支(合并到 main 之前)——Rebase 在最终合并前创建干净的线性历史。
  • 保持更新——将功能分支 rebase 到最新的 main 上,获取新更改而不产生合并提交。
  • 提交 PR 之前——经过 rebase 的干净提交更容易审查。
  • 清理本地提交——交互式 rebase 让你在分享之前压缩、重排和编辑提交。
# Update feature branch with latest main
$ git checkout feature
$ git rebase main

# If conflicts occur, resolve them, then:
$ git add .
$ git rebase --continue

交互式 Rebase:压缩、修正、重排

交互式 rebase(git rebase -i)是 Git 最强大的功能之一。它允许你在分享前修改提交。

$ git rebase -i HEAD~4

# Editor opens:
pick a1b2c3d Add user authentication
pick e4f5g6h Fix typo in auth
pick i7j8k9l Add password validation
pick m0n1o2p Fix lint error

# Change to:
pick a1b2c3d Add user authentication
fixup e4f5g6h Fix typo in auth       # merge into previous, discard message
pick i7j8k9l Add password validation
fixup m0n1o2p Fix lint error          # merge into previous, discard message

# Result: 2 clean commits instead of 4

# Commands:
# pick   = use commit as-is
# squash = merge into previous commit, keep message
# fixup  = merge into previous commit, discard message
# reword = use commit but edit message
# drop   = remove commit entirely

黄金法则:永远不要 Rebase 公共分支

如果分支已推送且其他人正在使用它,不要 rebase。Rebase 会重写提交哈希,其他开发者将面临分叉的历史和痛苦的合并冲突。

黄金法则:只 rebase 没有推送到共享远程仓库的提交,或只有你自己在使用的分支。

# ❌ DANGEROUS: Rebasing a shared branch
$ git checkout main
$ git rebase feature  # NEVER do this!

# ✅ SAFE: Rebasing your own feature branch
$ git checkout my-feature    # only I work on this
$ git rebase main            # safe!
$ git push --force-with-lease origin my-feature

Merge vs Rebase:完整对比

标准MergeRebase
历史记录非线性,保留所有分支线性,整洁
提交哈希保持不变改变(新哈希)
冲突解决一次性解决每个提交可能都要解决
可追溯性高(合并提交显示上下文)中(线性但缺少分支信息)
安全性安全(不重写历史)有风险(重写历史)
适合共享分支
适合个人分支
可撤销性简单(git revert)较难(需要 reflog)
git bisect较难(非线性)更容易(线性历史)

常见 Git 工作流

功能分支工作流

创建功能分支,开发,rebase 到 main,然后用 --no-ff 合并。这提供了带有清晰合并点的线性历史。

$ git checkout -b feature/login
# ... develop ...
$ git rebase main              # clean up history
$ git checkout main
$ git merge --no-ff feature/login  # merge with commit
$ git branch -d feature/login

Gitflow 工作流

使用 develop、feature、release 和 hotfix 分支。长期分支之间始终 merge(不要 rebase)。

# Always merge between long-lived branches
$ git checkout develop
$ git merge --no-ff feature/login
$ git checkout release/1.0
$ git merge --no-ff develop
$ git checkout main
$ git merge --no-ff release/1.0
$ git tag v1.0

主干开发

短期功能分支(< 1 天)。频繁 rebase 到 main,快速合并。高效团队的首选。

# Short-lived branch, rebase often
$ git checkout -b fix/typo
# ... quick fix ...
$ git rebase main
$ git checkout main
$ git merge fix/typo    # fast-forward
$ git push

危险场景

场景风险预防
Rebase main/master所有人的历史都被破坏永远不要 rebase main
Rebase 共享功能分支协作者面临分叉历史对共享分支使用 merge
git push --force覆盖远程更改使用 --force-with-lease
冲突解决后继续 rebase 出错代码丢失或损坏仔细检查每个冲突,使用 git rebase --abort 重来
Rebase 有合并提交的分支合并提交被展平,导致困惑使用 --rebase-merges 或避免

常见问题

可以撤销 rebase 吗?

可以。使用 git reflog 找到 rebase 前的提交哈希,然后用 git reset --hard <hash> 恢复。reflog 默认保留所有 HEAD 移动记录 90 天。

更新功能分支时应该 rebase 还是 merge?

如果只有你一个人在功能分支上工作,rebase 更好,历史更干净。如果其他人也在使用该分支,用 merge 避免重写共享历史。

什么是 git pull --rebase?

git pull --rebase 将你的本地提交重放到远程更改之上,而不是创建合并提交。它保持历史线性。

如果 rebase 了已推送的分支会怎样?

你需要强制推送(git push --force-with-lease)。已拉取旧提交的人将面临分叉历史。这就是为什么只应 rebase 你独自工作的分支。

squash merge 和 rebase + squash 一样吗?

结果类似,机制不同。GitHub 的 "Squash and merge" 按钮将所有提交压缩为一个并创建合并提交。Rebase -i 的 squash 让你选择压缩哪些提交,控制力更强。

开源贡献应该用哪个?

大多数开源项目倾向于经过 rebase 的干净提交。提交 PR 前,rebase 到最新 main 并压缩修正提交。

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

🔀Git Command Generator.gi.gitignore Generator±Text Diff Checker

相关文章

Git 命令速查表:开发者必备命令大全

完整的 Git 命令速查表:涵盖配置、分支、合并、变基、暂存和高级工作流程。

Git cherry-pick、revert 和 reset 详解

学习何时以及如何使用 git cherry-pick、revert 和 reset。理解每个命令的区别、用例和安全注意事项。