0 背景
在日常开发中,我们肯定遇到过这样的情况:
- 提交信息写错了(比如拼写错误);
- 提交信息太模糊(如 “fix bug”);
- 想把多个零散提交合并成一个有意义的提交;
- 或者只是想让 Git 历史看起来更整洁?
如果你不熟悉git, 可能会使用reset的方式撤销提交后再手动创建新的commit。。。单实际上, 交互式 rebase(git rebase -i)。可以轻松修改、合并、删除甚至重排历史提交——包括已经提交但尚未推送到远程仓库的记录。
今天,我们就来重点介绍如何用 git rebase - interactive 来 修改已有 commit 的信息。
1 基本原理
Git 中的每个 commit 都包含作者、时间、父提交和提交信息(message)。一旦你执行了 git commit,这个 commit 就被“固化”了。
但如果你还没把这个 commit 推送到共享仓库(比如 GitHub、GitLab),那么你完全可以在本地“重写历史”——这正是 git rebase -i 的用武之地。
⚠️ 注意:不要对已经推送到公共分支且他人可能基于其工作的 commit 执行 rebase,否则会引发协作混乱。
2 实际案例
假设我现在有这样的提交:
1 | > git log |
这里倒数第三个提交不符合规范, 我们想在提交信息前加上 feat: 前缀使其符合开源规范, 我们可以通过如下几个步骤完成:
2.1 启动交互式 rebase
先运行
1 | git rebase -i HEAD~3 |
这里的 HEAD~3 表示从当前 HEAD 往前数 3 个提交(包括当前),也就是说你会看到最近的 3 个提交。如果你想修改的是倒数第 3 个,那至少要包含它。
执行后,Git 会打开默认编辑器(如 Vim、Nano),显示类似内容:
1 | pick c9a40f6 fix: 修复部分环境下的编译报错 |
2.2 将 pick 改为 reword
找到你想修改的那一行(比如第二行),把 pick 改成 reword(或简写 r):
1 | pick c9a40f6 fix: 修复部分环境下的编译报错 |
保存并退出编辑器。
2.3 输入新的提交信息
Git 会立即弹出另一个编辑窗口,让你修改该 commit 的 message。这是我们就可以修改commit信息:
1 | feat: 修复wal清理检查的bug |
修改完成后保存退出。如果一切顺利,Git 会自动完成 rebase。你的 commit 信息就更新成功了!
你可以用 git log 查看结果:
1 | commit f72d75d57a7f8443022d0cbf1fc45466e73c3407 (HEAD -> master) |
你会发现那个 commit 的 hash 值变了(因为内容变了),但历史更清晰了。
3 rebase 介绍
3.1 基本原理
git rebase 是 Git 中一个用于整合分支历史的命令,它的主要作用是将一个分支上的提交“移动”或“重放”到另一个分支的顶端,从而让项目历史看起来更线性、整洁。假设你有如下历史:
1 | A---B---C main |
如果你在 feature 分支上执行:
1 | git rebase main |
Git 会把 feature 分支上自与 main 分叉以来的所有提交(即 D 和 E)“重新应用”到 main 的最新提交 C 之后,结果变成:
1 | A---B---C main |
注意:D’ 和 E’ 是新的提交对象(因为它们的父提交变了),虽然内容一样,但哈希值不同。
3.2 rebase vs merge
| 对比项 | git merge |
git rebase |
|---|---|---|
| 历史结构 | 保留真实合并历史,可能有分叉 | 生成线性历史,无分叉 |
| -commit 数量 | 可能增加一个“合并提交” | 不产生额外合并提交 |
| 安全性 | 安全,适合共享分支 | 不建议在已推送的公共分支上使用(会改写历史) |
| 可读性 | 真实反映开发过程 | 更干净、易读 |
3.3 常见用法
同步上游更新(推荐在本地分支使用)
1
2git checkout feature
git rebase main交互式 rebase(整理提交)
1
git rebase -i HEAD~3
可以 squash(合并)、edit(修改)、drop(删除)提交等。
变基到远程分支
1
git pull --rebase origin main
相当于先 fetch 再 rebase,避免不必要的 merge commit。
4 注意点
git rebase就是“把你的工作重新放到别人最新的工作后面”,让历史更干净,但要谨慎使用,尤其在多人协作时。