使用 Git 变基
在本例中,我们将介绍所有可用的 git rebase 命令,除 exec 之外。
我们将在终端输入 git rebase --interactive HEAD~7 来开始变基。我们常用的文本编辑器会显示以下行
pick 1fc6c95 Patch A
pick 6b2481b Patch B
pick dd1475d something I want to split
pick c619268 A fix for Patch B
pick fa39187 something to add to patch A
pick 4ca2acc i cant' typ goods
pick 7b36971 something to move before patch B
在本例中,我们将要
- 使用
squash将第五个提交 (fa39187) 合并到“Patch A”提交 (1fc6c95) 中。 - 将最后一次提交 (
7b36971) 向上移动到“Patch B”提交 (6b2481b) 之前,并保持为pick。 - 使用
fixup将“A fix for Patch B”提交 (c619268) 合并到“Patch B”提交 (6b2481b) 中,并忽略提交信息。 - 使用
edit将第三个提交 (dd1475d) 拆分为两个更小的提交。 - 使用
reword修正拼写错误的提交 (4ca2acc) 的提交信息。
呼!听起来工作量很大,但只要一步一步来,我们就能轻松完成这些更改。
首先,我们需要将文件中的命令修改为以下形式
pick 1fc6c95 Patch A
squash fa39187 something to add to patch A
pick 7b36971 something to move before patch B
pick 6b2481b Patch B
fixup c619268 A fix for Patch B
edit dd1475d something I want to split
reword 4ca2acc i cant' typ goods
我们已将每行的命令从 pick 更改为我们关注的命令。
现在,保存并关闭编辑器;这将启动交互式变基。
Git 跳过第一个变基命令 pick 1fc6c95,因为它无需执行任何操作。接着处理下一个命令 squash fa39187。由于此操作需要你提供输入,Git 会再次打开你的文本编辑器。它打开的文件大致如下
# This is a combination of two commits.
# The first commit's message is:
Patch A
# This is the 2nd commit message:
something to add to patch A
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Not currently on any branch.
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: a
#
该文件是 Git 用来说明“嘿,我即将对这个 squash 做的操作”的方式。它列出了第一个提交的消息 (“Patch A”),以及第二个提交的消息 (“something to add to patch A”)。如果你对这些提交信息满意,只需保存文件并关闭编辑器。否则,你可以直接修改文本来更改提交信息。
编辑器关闭后,变基继续进行
pick 1fc6c95 Patch A
squash fa39187 something to add to patch A
pick 7b36971 something to move before patch B
pick 6b2481b Patch B
fixup c619268 A fix for Patch B
edit dd1475d something I want to split
reword 4ca2acc i cant' typ goods
Git 处理两个 pick 命令(对应 pick 7b36971 和 pick 6b2481b)。它还会处理 fixup 命令(fixup c619268),因为该命令不需要交互。fixup 将 c619268 的更改合并到其前面的提交 6b2481b 中。两者将拥有相同的提交信息:“Patch B”。
Git 执行到 edit dd1475d 操作时会暂停,并在终端打印以下信息
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
此时,你可以编辑项目中的任意文件以进行额外修改。每进行一次修改后,需要创建一个新的提交,可使用 git commit --amend 命令。当完成所有修改后,运行 git rebase --continue。
随后 Git 执行到 reword 4ca2acc 命令时,会再次打开你的文本编辑器,并显示以下信息
i cant' typ goods
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Not currently on any branch.
# Changes to be committed:
# (use "git reset HEAD^1 <file>..." to unstage)
#
# modified: a
#
和之前一样,Git 正在显示供你编辑的提交信息。你可以修改文本(“i cant' typ goods”),保存文件并关闭编辑器。Git 将完成变基并返回终端。
将已变基的代码推送到 GitHub
由于你已经修改了 Git 历史,常规的 git push origin 将无法 工作。你需要通过“强制推送”最新更改来修改该命令
# Don't override changes
$ git push origin main --force-with-lease
# Override changes
$ git push origin main --force
警告
强制推送影响重大,因为它会更改分支的提交历史顺序。请谨慎使用,尤其是在有多人访问仓库的情况下。