git rebase的核心思想是**“改变一个分支的基底(base)”**,它让你有机会将一系列提交移动到一个新的父提交上,并在此过程中修改它们。

rebase主要用于整理和清理提交历史,让提交记录更清晰、更线性。与git merge不同,merge是合并两个分支的历史,并创建一个新的“合并提交”,而rebase则是通过“重写”历史的方式,将你的提交应用到另一个提交的顶部。

1. git rebase -i (交互式变基) 的作用

当你运行 git rebase 并加上 -i (interactive) 选项时,Git 会进入交互模式。这个模式是 git rebase 最强大的功能,它不会直接执行操作,而是弹出一个编辑器,让你决定如何处理每一笔提交

你可以执行以下操作:

  • pick:保留该提交。
  • reword:保留提交,但修改提交信息。
  • edit:保留提交,但停下来让你进行修改(比如修改文件内容或拆分提交)。
  • squash:将该提交与上一笔提交合并。
  • fixup:类似于squash,但会丢弃该提交的提交信息,只使用上一笔提交的信息。
  • drop:删除该提交。

2. 结合例子进行操作

362cc92 (HEAD -> main) scheme实践
d23b2b0 mvp实践初始化
406eca8 完善 popupWindow
00cf2f6 Create README.md
cb860d6 学习requestLayout
2858d56 完善 popupWindow
d1e2353 学习 Broadcast & Service
f1a04cd ViewTreeObserver学习
8b6a107 init repo

目标是合并这三笔不连续的提交:1e8601ca57fa8e0ac2358

第一步:确定变基的范围

运行的命令是git rebase -i f1a04cd

  • f1a04cd基底(base)。这个哈希值代表的提交,是你希望新提交历史从它开始的地方。它也是你不想被修改的、最老的一笔提交。
  • rebase -i会列出所有在f1a04cd之后、HEAD之前的提交。

第二步:在编辑器中重新排列和标记提交

Git 会弹出一个编辑器,显示从f1a04cd之后的提交列表。要合并不连续的提交,必须手动重新排列(reorder)它们,让它们变得相邻。

假设在编辑器里,你把三笔要合并的提交放在了一起:

pick 1e8601c Broadcast学习
pick a57fa8e update
pick 0ac2358 学习 Broadcast & Service
...

接下来,你使用squash命令来合并它们。你对第一笔提交使用pick来保留它,然后对后续两笔提交使用squash,将它们合并到第一笔提交中。

修改后的内容如下:

pick 1e8601c Broadcast学习
s 0ac2358 学习 Broadcast & Service
s a57fa8e update
...

(注:Git 的合并顺序是从上到下。这里我调整了a57fa8e0ac2358的顺序,确保它们都合并到1e8601c中。)

第三步:编写新的提交信息

保存并关闭编辑器后,Git 会将这三笔提交合并成一笔。然后,它会再次弹出一个编辑器,让你为合并后的新提交编写一个清晰的提交信息。

这个新的提交信息应该能够概括这三笔提交的所有工作内容,例如:“合并关于 Broadcast & Service 的所有提交”。

完成这些步骤后,你的 Git 历史中,这三笔提交将被一个全新的提交所取代,历史记录变得更简洁。

rebasemerge的区别和注意事项

  • rebase是一种非破坏性重写历史的方法。它不会创建新的合并提交,而是通过重新应用提交,来保持一个线性的、干净的提交历史。
  • merge合并历史。它会创建一个新的合并提交,保留了分支合并的原始记录。
  • 警告:永远不要对已经推送到共享远程仓库的提交进行rebase,这会造成历史分歧,给其他协作者带来麻烦。rebase只应该在本地分支上进行清理工作。

^ 符号的用法

  • commit_hash^: 指向 commit_hash的父提交。
  • commit_hash^^: 指向 commit_hash的祖父提交(父提交的父提交)。
  • commit_hash^N: 当一个提交是合并提交(merge commit)时,它会有多个父提交。^N可以用来指定第 N 个父提交。例如,^1指向第一个父提交,^2指向第二个父提交。

结合你的例子

在你之前的命令git rebase -i 05503ab^中:

  • 05503ab是你想要重命名的提交。
  • 05503ab^指向05503ab前一笔提交

因此,git rebase -i 05503ab^这条命令的意思是:“从05503ab的父提交开始,进入交互式变基模式。”

这样做是为了让05503ab成为你可以操作的第一笔提交,从而让你有机会使用reword命令来修改它的提交信息。

^~的区别

Git 还有一个类似的符号~,但它们的使用场景略有不同:

  • ~N: 表示从当前提交开始,往后回溯 N 步。它总是沿着主线父提交移动。
    • HEAD~1等同于HEAD^
    • HEAD~2等同于HEAD^^
  • ^: 主要用来处理合并提交,可以精确地指定要操作的是哪一个父提交。

在处理非合并提交时,^~都可以达到回溯一步的效果,但~在回溯多步时更常用,因为它不需要重复书写。

更新: 2025-08-05 16:52:24
原文: https://www.yuque.com/dongpozhouzi-mshe3/zhm85g/xer1enm5f9cxzhwy


相关笔记