为了修改在提交历史中较远的提交,必须使用更复杂的工具。Git没有一个改变历史工具,但是可以使用变基工具来变基一系列提交,基于它们原来的 HEAD 而不是将其移动到另一个新的上面。通过 交互式变基工具,可以在任何想要修改的提交后停止,然后修改信息、添加文件或做任何想做的事情。
可以通过给 git rebase 增加 -i 选项来交互式地运行变基。必须指定想要重写多久远的历史,这可以通过告诉命令将要变基到的提交来做 到。
例如,如果想要修改 最近三次提交信息,或者那组提交中的任意一个提交信息,将想要修改的最近一次提交的父提交 作为参数传递给 git rebase -i 命令,即 HEAD~2^ 或 HEAD~3。
$git rebase -i HEAD~3
1
pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
# Rebase 710f0f8..a5f4a0d onto 710f0f8## Commands:# p, pick = use commit# r, reword = use commit, but edit the commit message# e, edit = use commit, but stop for amending# s, squash = use commit, but meld into previous commit# f, fixup = like "squash", but discard this commit's log message# x, exec = run command (the rest of the line) using shell# b, break = stop here (continue rebase later with 'git rebase
--continue')
# d, drop = remove commit
# l, label s
# . message (or the oneline, if no original merge commit was# . specified). Use -c to reword the commit message.## These lines can be re-ordered; they are executed from top to bottom.
edit f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
1
2
3
当保存并退出编辑器时,Git 将你带回到列表中的最后一次提交,把你送回命令行并提示以下信息:
$ git rebase -i HEAD~3
Stopped at f7f3f6d... changed my name a bit
You can amend the commit now, with
git commit --amend
Once youre satisfied with your changes, run
git rebase --continue
# Commands:# p, pick = use commit# r, reword = use commit, but edit the commit message# e, edit = use commit, but stop for amending# s, squash = use commit, but meld into previous commit# f, fixup = like "squash", but discard this commit's log message# x, exec = run command (the rest of the line) using shell# b, break = stop here (continue rebase later with 'git rebase
--continue')
# d, drop = remove commit
# l, label = label current HEAD with a name
# t, reset = reset HEAD to a label
# m, merge [-C | -c ] [# ]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was# . specified). Use -c to reword the commit message.#
pick f7f3f6d changed my name a bit
squash 310154e updated README formatting and added blame
squash a5f4a0d added cat-file
1
2
3
当保存并退出编辑器时,Git 应用所有的三次修改然后将你放到编辑器中来合并三次提交信息:
# This is a combination of 3 commits.# The first commit's message is:
changed my name a bit
# This is the 2nd commit message:
updated README formatting and added blame
# This is the 3rd commit message:
added cat-file
1
2
3
4
5
6
7
当你保存之后,你就拥有了一个包含前三次提交的全部变更的提交。
拆分提交
拆分一个提交会撤消这个提交,然后多次地部分地暂存与提交直到完成你所需次数的提交。
例如,假设想要拆分三次提交的中间那次提交。想要将它拆分为两次提交:第一个“updated README formatting”,第二个 “added blame” 来代替原来的“updated README formatting and added blame”。可以通过修改 rebase -i 的脚本来做到这点,将要拆分的提交的指令修改为“edit”:
pick f7f3f6d changed my name a bit
edit 310154e updated README formatting and added blame
pick a5f4a8d added cat-file
1
2
3
然后,当脚本带你进入到命令行时,重置那个提交,拿到被重置的修改,从中创建几次提交。当保存并退出编辑器时,Git带你到列表中第一个提交的父提交,应用第一个提交(f7f3f6d),应用第二个提交( 310154e),然后让你进入命令行。那里,可以通过 git reset HEAD 做一次针对那个提交的混合重置,实际上将会撤消那次提交并将修改的文件取消暂存。现在可以暂存并提交文件直到有几个提交,然后当完成时运行 git rebase--continue: