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目标是合并这三笔不连续的提交:1e8601c、a57fa8e、0ac2358。
第一步:确定变基的范围
运行的命令是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 的合并顺序是从上到下。这里我调整了a57fa8e和0ac2358的顺序,确保它们都合并到1e8601c中。)
第三步:编写新的提交信息
保存并关闭编辑器后,Git 会将这三笔提交合并成一笔。然后,它会再次弹出一个编辑器,让你为合并后的新提交编写一个清晰的提交信息。
这个新的提交信息应该能够概括这三笔提交的所有工作内容,例如:“合并关于 Broadcast & Service 的所有提交”。
完成这些步骤后,你的 Git 历史中,这三笔提交将被一个全新的提交所取代,历史记录变得更简洁。
rebase与merge的区别和注意事项
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