Git 没有改变历史的工具,但是可以使用交互式变基来修改历史,该命令为 git rebase -i
如果想修改最近三次提交,那就要将最近的第三次提交的 父提交 作为参数传递给 git rebase -i,即 HEAD~2^HEAD~3 ,如下所示:

  1. $ git rebase -i HEAD~3
  2. pick cdb4e0d modified readme.md file
  3. pick 30b0518 add H1 to index.html
  4. pick 608b87b signed commit

就可以看到,他将最近三次提交都展示出来了。值得注意的是,他的顺序是和 git log 的显示顺序是 相反 的。因为它会依次的根据指令进行提交的修改,所以旧的提交就列在最上面,按照顺序修改,就可以形成 git log 的顺序了。
当然,也可以指定区间进行变基,但必须是旧提交在前,新提交在后

  1. $ git rebase -i 8fcd8b6 c87d6f8
  2. pick 4b6f30d add index file
  3. pick b445fad modified to a README.md file
  4. pick 33c3895 add next array file
  5. pick c87d6f8 create kmp cpp file

可以看到,它变基的区间是 8fcd8b6 的 子提交 与 c87d6f8 之间来进行变基。
根据上面的指令,必须要知道一个提交的父提交才能进行交互式变基。那如果要重写根提交(第一个提交)怎么办?比较笨的方法是在提交列表中,手动将根提交添加进来。更简单的方法是 git rebase -i --root
需要注意的是,这是一个变基命令,在你变基的范围内,每一个修改了的提交都会被重写。所以确保变基的提交没有推送到远程,避免不必要的麻烦 。

命令

在交互式变基中,我们可以看到很多操作:

  1. # Commands:
  2. # p, pick <commit> = use commit
  3. # r, reword <commit> = use commit, but edit the commit message
  4. # e, edit <commit> = use commit, but stop for amending
  5. # s, squash <commit> = use commit, but meld into previous commit
  6. # f, fixup <commit> = like "squash", but discard this commit's log message
  7. # x, exec <command> = run command (the rest of the line) using shell
  8. # b, break = stop here (continue rebase later with 'git rebase --continue')
  9. # d, drop <commit> = remove commit
  10. # l, label <label> = label current HEAD with a name
  11. # t, reset <label> = reset HEAD to a label
  12. # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
  13. # . create a merge commit using the original merge commit's
  14. # . message (or the oneline, if no original merge commit was
  15. # . specified). Use -c <commit> to reword the commit message.
  16. #
  17. # These lines can be re-ordered; they are executed from top to bottom.
  18. #
  19. # If you remove a line here THAT COMMIT WILL BE LOST.
  20. #
  21. # However, if you remove everything, the rebase will be aborted.
  22. #
  23. # 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