Git Rebase

git rebase 的核心用法:交互式变基、onto、冲突处理,以及"不要 rebase 已推送提交"的黄金规则。

#type / howto #status / growing #tech / ops #resource / git

[!info] related notes

Git Rebase

一句话定义

rebase 把一系列提交”移植”到新的基点上,让历史变成线性。

rebase vs merge

场景rebasemerge
历史形态线性,干净保留分支结构,有合并提交
冲突处理逐个提交解决一次性解决
已推送历史会改写(危险)不改写(安全)
适用场景同步主分支、整理提交合并功能分支到主分支

基本用法:同步主分支

# 当前在 feature 分支,想把 main 的最新提交同步过来
git checkout feature
git rebase main

# 效果:feature 的提交被"摘下来",重新放到 main 最新提交之后
# 原来:  main ---A---B---C
#                  \
#                   D---E  (feature)
#
# rebase 后:  main ---A---B---C
#                              \
#                               D'---E'  (feature,新的提交哈希)

交互式 rebase(最常用)

# 修改最近 3 个提交
git rebase -i HEAD~3

打开编辑器后的操作指令:

pick   abc1234 第一个提交
squash def5678 第二个提交(合并到上一个)
reword ghi9012 第三个提交(修改提交信息)
drop   jkl3456 删除这个提交
edit   mno7890 暂停,允许修改内容
fixup  pqr1234 类似 squash,但丢弃此提交信息

# pick   = 保留
# squash = 合并到前一个提交,保留两者信息
# fixup  = 合并到前一个提交,丢弃此提交信息
# reword = 保留内容,修改提交信息
# drop   = 删除提交
# edit   = 暂停在此提交,允许修改

实战:压缩提交

# 把 5 个小提交压缩成 1 个
git rebase -i HEAD~5

# 编辑器中:
pick   abc1234 feat: 初始化用户模块
fixup  def5678 fix: 拼写错误
fixup  ghi9012 fix: 格式化代码
fixup  jkl3456 feat: 添加邮箱验证
fixup  mno7890 fix: 修复验证逻辑

# 结果:只剩一个干净的提交

实战:修改提交信息

git rebase -i HEAD~1
# 把 pick 改为 reword,保存后会打开编辑器修改提交信息

--onto 用法

# 把 feature 分支上"不在 A 上"的提交,移植到 B 上
git rebase --onto B A feature

# 典型场景:feature 从 develop 拉出,但要改到 main 上
git rebase --onto main develop feature
原始:
  main ---M1---M2
              \
  develop      D1---D2
                    \
  feature           F1---F2

rebase --onto main develop feature 后:
  main ---M1---M2
                 \
  feature         F1'---F2'  (只移植了 F1、F2,不包含 D1、D2)

冲突处理

# rebase 过程中遇到冲突
git rebase main
# CONFLICT (content): Merge conflict in src/app.js

# 1. 解决冲突后
git add src/app.js

# 2. 继续 rebase
git rebase --continue

# 3. 如果想放弃整个 rebase
git rebase --abort

# 4. 如果想跳过当前提交
git rebase --skip

冲突处理技巧:

# 查看哪些文件有冲突
git status

# 查看冲突详情
git diff

# 使用某个版本的文件
git checkout --ours src/app.js    # 用当前分支的版本
git checkout --theirs src/app.js  # 用目标分支的版本

黄金规则

不要 rebase 已经推送到公共仓库的提交。

原因:rebase 会改写提交哈希。如果别人基于旧提交工作,rebase 后他们的分支基点就不存在了。

# 安全:rebase 本地未推送的提交
git rebase main  # 本地 feature 分支,还没 push

# 危险:rebase 已推送的提交
git rebase main  # feature 分支已经 push 过,别人可能在用
git push --force  # 强制推送会覆盖别人的提交

安全替代方案:

# 如果必须对已推送的分支做 rebase,先通知协作者
# 或者用 merge 代替
git merge main

rebase 的自动化策略

# rebase 时自动处理空白字符问题
git rebase --whitespace=fix main

# 自动 stash 未提交的更改
git rebase --autostash main

# rebase 时保留合并提交
git rebase --remerges-merges main

常见误区

  • rebase 不是”更好的 merge”:两者适用场景不同
  • rebase 后的提交是新的:哈希变了,不是原来的提交
  • git pull --rebase 等于 fetch + rebase:比默认的 fetch + merge 历史更干净
  • 冲突解决后用 add 而不是 commit:rebase 的流程和 merge 不同
创建于 2026/5/27 更新于 2026/5/27