变基:什么是 rebase、如何操作以及与 Git 协同工作

作者: IT Sectr 发布日期: 2026-08-01 阅读时间: 9 分钟

Rebase — 是 Git 中的一种操作,它将提交从一个分支移动到另一个分支的顶端,创建无需多余 merge 提交的线性历史。与合并不同,rebase 会重写历史:每个被移动的提交都会获得新的哈希,因为其父提交发生了变化。根据 Git 文档(2026),rebase 用于在创建 pull request 之前将功能分支与 main 的当前状态同步。Git rebase 命令是在使用 Git Flow 的项目中保持历史整洁的主要工具之一。

要点

  • Rebase — 将功能分支的提交移动到目标分支的顶端,生成新的哈希。
  • 线性历史 — rebase 的主要优势:没有 merge 提交使阅读变更日志更简单。
  • 交互式 rebase 使用 -i 标志可以在发布前合并、重命名和删除提交。
  • 公共分支 — 对于其他开发人员使用的分支禁止 rebase,因为它会重写历史。
  • 可能发生冲突 — 移动提交时,Git 可能要求对每个提交单独解决冲突。

Git 中的 rebase 是什么

Rebase — 是一条 Git 命令,它将当前分支重新定位到指定的分支:获取当前分支的所有提交,临时保存它们,将分支指针移动到目标提交,然后顺序地将保存的提交应用到其顶端。结果 — 历史看起来就像开发人员直接从目标分支的最后一个提交开始工作一样。

基本语法:git rebase main — 当位于功能分支时,此命令将所有功能提交移动到 main 的顶端。Git 对每个提交单独使用三路合并策略。如果提交 A 已存在于目标分支中(通过哈希确定),Git 会自动跳过它,从而避免重复变更。

Rebase 还支持用于移动部分提交的 onto 模式:git rebase --onto target start end — 此形式允许从一个分支提取一系列提交并将其应用到另一个分支的顶端。例如,git rebase --onto main feature~3 feature 会将功能分支的最后三个提交移动到 main 的顶端。

bash
# 切换到功能分支
git checkout feature

# 将功能变基到 main
git rebase main

# 变基成功后 — 历史是线性的
git log --oneline --graph

# 将最后 3 个提交移动到 main
git rebase --onto main HEAD~3 HEAD

Rebase vs Merge:主要区别

Rebase 和 merge 解决相同的任务 — 合并来自不同分支的变更 — 但使用根本不同的方式。Merge 通过创建具有两个父提交的 merge 提交来保留完整的合并历史。Rebase 重写历史,使其成为线性。它们之间的选择取决于团队的工作流程和使用仓库的规则。

主要区别 — 如何记录合并的事实。Merge 保留:“在这一点上我们将功能合并到了 main” — 这对项目历史有信息价值,但在频繁合并时会污染日志。Rebase 显示:“功能提交是从 main 的最后状态顺序完成的” — 这很干净,但隐藏了工作并行进行的事实。

第二个区别 — 冲突处理。在 merge 中,冲突解决一次,解决方案记录在 merge 提交中。在 rebase 中,每个被移动的提交都可能引发冲突,每个冲突都需要单独解决。这更耗时,但可以更精确地控制哪些变更进入最终版本。

标准RebaseMerge
历史线性,无 merge 提交非线性,有 merge 提交
提交哈希被重写(新)原始保留
冲突每个提交单独处理在 merge 提交中一次处理
公共分支禁止允许
取消命令git rebase --abortgit merge --abort

交互式 rebase:命令和标志

交互式 rebase (git rebase -i) — 是 Git 打开一个编辑器显示提交列表以及每个提交可用操作的模式。开发人员可以在推送到远程仓库之前重写历史。这是在功能分支中保持提交整洁的主要工具。

交互模式下可用的命令:pick(保持提交不变)、reword(更改提交消息)、edit(停止以进行更改)、squash(与上一个提交合并,保留两者消息)、fixup(合并,丢弃消息)、drop(删除提交)。每个命令在打开的编辑器中写在提交哈希之前。

Squash 和 fixup — 最常用的合并提交命令。如果开发人员在工作过程中做了 5 个小修改提交,squash 会将它们合并为一个具有有意义消息的逻辑提交。Fixup 对于修正拼写错误很有用:更改会进入前一个提交而不保存自己的消息。

bash
# 为最后 4 个提交打开编辑器
git rebase -i HEAD~4

# 编辑器将显示:
pick a1b2c3d Add authentication
pick e4f5g6h Fix typo in login
squash i6j7k8l Additional login fixes
pick m9n0o1p Add auth tests

# 保存后 — Git 执行变基
# 并打开编辑器以输入合并后的提交消息

# 不打开编辑器的自动压缩
git rebase -i HEAD~4 --autosquash

--autosquash 标志自动为消息以 fixup! 或 squash! 开头的提交设置 fixup/squash。如果开发人员提前标记提交以供后续合并,这可以加快工作速度。--committer-date-is-author-date 标志在变基时保留提交的原始日期 — 有助于在历史中保持时间顺序。

Rebase 时的冲突解决

Rebase 时的冲突 当 Git 由于与目标分支中的变更冲突而无法自动应用被移动的提交时发生。与合并不同,合并时冲突解决一次,而 rebase 中每个提交都可能引起冲突,需要从最旧到最新按顺序为每个提交解决。

当冲突发生时,Git 暂停 rebase 并报告哪个提交引起了问题。开发人员打开冲突文件(Git 用 <<<<<<<, =======, >>>>>>> 标记标记冲突区域),编辑它,添加到索引(git add),然后使用 git rebase --continue 命令继续 rebase。如果找不到解决方案 — git rebase --abort 完全取消变基。

提示:对于多个冲突,使用 git mergetool 更有效,它会打开可视化编辑器来解决冲突。也可以跳过有问题的提交(git rebase --skip),但这会将其变更从最终历史中删除,这很少是正确的解决方案。

bash
# 开始带冲突的变基
git rebase main
# 自动合并 file.txt
# 冲突(内容):file.txt 中的合并冲突

# 检查状态
git status
# 两者均已修改:file.txt

# 编辑冲突部分 → git add → 继续
git add file.txt
git rebase --continue

# 如有疑问 — 取消
git rebase --abort

何时不能进行 rebase

Rebase 的黄金法则:永远不要变基已经推送到远程仓库并可供其他开发人员使用的提交。由于 rebase 会重写提交的哈希,同事在尝试同步时会遇到冲突 — 他们的本地历史将与重写后的远程历史不一致。

绝对禁止 rebase 的情况:如果有人已经基于您的提交创建了分支(例如,您的同事从您的功能分支创建了功能分支),更改历史会破坏他的工作。在这种情况下,应该使用 merge。同样不建议在截止日期前立即进行 rebase — 解决冲突时的错误可能耗时超出预期并阻塞发布。

例外:如果分支仅由一个开发人员使用(个人功能分支,未发布或以草稿模式发布),推送前的 rebase 是 标准做法。在发布和开始团队工作后 — 仅使用 merge。GitHub 和 GitLab 默认提供 squash merge 作为折中方案:它将提交合并为一个,但不重写目标分支的历史。

  • 公共分支(main, develop, release)— rebase 完全禁止。
  • 他人提交 — 如果分支包含其他开发人员的提交,rebase 不可接受。
  • 发布前 — 冲突风险更高:在截止日期前一天 merge 更安全。
  • 带标签的分支 — 移动带标签的提交违反了语义化版本控制约定。
  • CI/CD 绑定哈希 — 一些部署系统通过提交哈希识别构建;rebase 会破坏跟踪。

使用 rebase 的实践工作流程

在现代团队中,最常使用 面向 rebase 的工作流程 与 GitHub Flow 结合。过程如下:开发人员从 main 创建功能分支,在其中工作,通过 git rebase main 定期同步,并在创建 pull request 之前执行交互式 rebase 以清理历史。

创建 PR 后(如果需要从 main 拉取新变更),使用 git pull --rebase main 代替普通的 git pull。这允许在不创建不必要的 merge 提交的情况下拉取变更。带有 --rebase 标志的 git pull 相当于 git fetch + git rebase — Git 首先加载新提交,然后将本地变更变基到它们之上。

Git 允许将 rebase 设置为 pull 的默认行为:git config --global pull.rebase true。配置后,git pull 始终执行 rebase 而不是 merge。如果需要普通的 pull — 使用 git pull --no-rebase。许多团队也启用 autostash:git config --global rebase.autoStash true — 这会自动在 rebase 前隐藏未提交的更改并在之后恢复。

常见问题

在 Git 中变基提交是什么意思?

变基 — 意味着执行 git rebase:将当前分支的提交移动到另一个分支的顶端。结果,历史变得线性,每个提交获得新的哈希,并且不会创建 merge 提交。该命令用于在日志中无需额外合并点的情况下同步分支。

Rebase 与 merge 有什么区别?

Merge 创建具有两个父提交的 merge 提交,保留并行历史和原始哈希。Rebase 重写历史 — 提交获得新的哈希,历史变得线性。Merge 对公共分支更安全,rebase 提供更清晰的日志。

如何进行交互式 rebase?

git rebase -i HEAD~N 命令打开一个编辑器,显示最近的 N 个提交。对于每个提交,可以选择操作:pick(保留)、reword(重命名)、edit(修改)、squash(与上一个合并)、fixup(合并但不保留消息)、drop(删除)。保存后,Git 应用选定的更改。

为什么 rebase 对公共分支有危险?

Rebase 会重写提交的哈希,使历史与其他开发人员中相同提交的副本不兼容。如果同事已经通过 git pull 收到了您的提交,而您之后进行了变基,他的 git push 将被拒绝,git pull 将创建重复的提交和冲突。

Rebase 执行后可以撤销吗?

完成前 — git rebase --abort 完全取消。完成后,可以通过 git reflog 恢复之前的状态 — 找到变基前的提交哈希并对其实行 git reset --hard。Reflog 默认保存 HEAD 移动历史 30 天。

总结

  • Rebase — 将提交移动到新基点的操作,创建无 merge 提交的线性历史。
  • 命令 git rebase main 将当前分支变基到 main,顺序地将提交应用到顶端。
  • 交互模式 -i 允许合并(squash)、重命名(reword)和删除(drop)提交。
  • 冲突 在 rebase 中为每个提交单独解决,与 merge 不同。
  • 公共分支 — 变基被禁止,因为它会破坏其他开发人员的历史。
  • git pull --rebase — 与远程分支安全同步且无需 merge 提交的方式。
  • Git reflog — 允许在 30 天内从失败的 rebase 中恢复。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读