Git 没有改变历史的工具,但是可以使用交互式变基来修改历史,该命令为 git rebase -i
如果想修改最近三次提交,那就要将最近的第三次提交的 父提交 作为参数传递给 git rebase -i,即 HEAD~2^ 或 HEAD~3 ,如下所示:
$ git rebase -i HEAD~3pick cdb4e0d modified readme.md filepick 30b0518 add H1 to index.htmlpick 608b87b signed commit
就可以看到,他将最近三次提交都展示出来了。值得注意的是,他的顺序是和 git log 的显示顺序是 相反 的。因为它会依次的根据指令进行提交的修改,所以旧的提交就列在最上面,按照顺序修改,就可以形成 git log 的顺序了。
当然,也可以指定区间进行变基,但必须是旧提交在前,新提交在后
$ git rebase -i 8fcd8b6 c87d6f8pick 4b6f30d add index filepick b445fad modified to a README.md filepick 33c3895 add next array filepick c87d6f8 create kmp cpp file
可以看到,它变基的区间是 8fcd8b6 的 子提交 与 c87d6f8 之间来进行变基。
根据上面的指令,必须要知道一个提交的父提交才能进行交互式变基。那如果要重写根提交(第一个提交)怎么办?比较笨的方法是在提交列表中,手动将根提交添加进来。更简单的方法是 git rebase -i --root
需要注意的是,这是一个变基命令,在你变基的范围内,每一个修改了的提交都会被重写。所以确保变基的提交没有推送到远程,避免不必要的麻烦 。
命令
在交互式变基中,我们可以看到很多操作:
# Commands:# p, pick <commit> = use commit# r, reword <commit> = use commit, but edit the commit message# e, edit <commit> = use commit, but stop for amending# s, squash <commit> = use commit, but meld into previous commit# f, fixup <commit> = like "squash", but discard this commit's log message# x, exec <command> = run command (the rest of the line) using shell# b, break = stop here (continue rebase later with 'git rebase --continue')# d, drop <commit> = remove commit# l, label <label> = label current HEAD with a name# t, reset <label> = reset HEAD to a label# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]# . create a merge commit using the original merge commit's# . message (or the oneline, if no original merge commit was# . specified). Use -c <commit> to reword the commit message.## These lines can be re-ordered; they are executed from top to bottom.## If you remove a line here THAT COMMIT WILL BE LOST.## However, if you remove everything, the rebase will be aborted.## Note that empty commits are commented out
下列操作用到的频率比较高:
pick: 使用该提交reword: 使用该提交,会直接进入提交信息来修改提交信息edit: 使用该提交,会短暂回到命令行,来进行提交(可以在命令行中增加提交)squash: 使用该提交,并且与上一个提交合并fixup: 与squash一样,但是会丢弃提交信息exec: 使用 shell 运行命令drop: 删除该提交filter-branch
filter-branch 可以全局改写提交历史,比如: ``` $ git filter-branch —tree-filter ‘rm -f passwords.txt’ HEAD
``
该命令会检出项目的每一个提交后运行rm -f passwords.txt` 然后重新提交结果。更多详情可以查看 pro git
