revert 命令会在历史中增加一条commit记录,用来撤销之前的commit提交记录。
对比回退的命令:amend、revert、reset

  • git commit -amend:新的提交覆盖上次提交的内容
  • git revert:新增一个提交记录commit,用来撤销之前的commit
  • git reset:直接回退到指定的commit历史,不会新增提交记录。包括3中模式
    • —soft:只回退本地仓库的代码,工作区和暂存区的内容不回退
    • —mixed:回退本地仓库和暂存区,工作区的内容不回退
    • —hard:工作区、暂存区、本地仓库都进行回退。
  • git restore .:撤销工作区的内容修改
    • git restore —staged . :撤销暂存区的内容修改

      revert命令的原理

      git revert命令用来撤销之前提交的版本记录,来达到修改的目的。比如提交了3个版本,突然发现版本2有bug,想撤销版本2,就可以使用git revert命令,同时会生成新的版本4提交历史记录。这样最新的版本里就保留版本3的内容,同时撤销了版本2的内容。
      git后悔药-revert - 图1
      • revert命令是撤回一个记录;
      • reset命令是重置到一个记录。
      • revert命令不会删除任何commit记录,而是新增一条revert操作的commit记录

revert命令的使用

新建一个测试代码git仓库,提交记录如下;

  1. shuais-MacBook-Pro:revert shuai$ git alog
  2. * ec2ab45 (HEAD -> master) v4 w
  3. * 00e34c1 v3 w
  4. * cb4a3c0 v2
  5. * 6988773 v1

v3和v4中存在错误,需要进行回退操作。
git后悔药-revert - 图2
此时head指针在v4,即ec2ab45的commit上。需要把head指向v2即可达到目的。

根据之前的reset,可以很容易操作git reset --hard ec2ab45但是这样存在弊端,会把v3和v4的提交给隐藏掉,如果有天突然觉得v3和v4版本是正确的需要恢复,就不那么容易操作,【当然也可通过reflog可以查看,然后恢复】。 由于会撤销掉一些commit记录,很多公司是禁止使用reset命令。这时就必须是revert。

git revert commit-id

  1. # 撤销v4提交记录,然后会出现一个编辑文本框,如下面编辑框
  2. shuais-MacBook-Pro:revert shuai$ git revert ec2ab45
  3. [master cf8a19a] Revert "v4 w"
  4. 1 file changed, 1 insertion(+), 2 deletions(-)
  5. # 撤销v3提交记录,然后会出现一个编辑文本框,如下面编辑框
  6. shuais-MacBook-Pro:revert shuai$ git revert 00e34c1
  7. [master 1788aaa] Revert "v3 w"
  8. 1 file changed, 1 insertion(+), 2 deletions(-)
  9. # 查看历史,可以看到新增了revert v4和revert v3
  10. shuais-MacBook-Pro:revert shuai$ git log --oneline
  11. 1788aaa (HEAD -> master) Revert "v3 w"
  12. cf8a19a Revert "v4 w"
  13. ec2ab45 v4 w
  14. 00e34c1 v3 w
  15. cb4a3c0 v2
  16. 6988773 v1

revert命令后的编辑弹出框,可以进行编辑后保存。

  1. Revert "v3 w"
  2. This reverts commit 00e34c14551df71df0bed4278947f33ba97aca67.
  3. # Please enter the commit message for your changes. Lines starting
  4. # with '#' will be ignored, and an empty message aborts the commit.
  5. #
  6. # On branch master
  7. # Changes to be committed:
  8. # modified: readme.txt

revert命令的作用是通过创建一个新的版本commit,来回退到目标版本,HEAD指针指向了新生成的commit,而不是原来的目标commit。

对比revert和reset的示意图

git后悔药-revert - 图3

revert时需要注意

  • 工作区或者暂存区存在修改内容未提交,则会提示先提交或者存储起来
  • 在移除过程中出现冲突,先解决冲突
    • 使用git add命令添加修改的冲突文件到暂存区,使用git revert —continue 来继续操作
    • 如果要放弃revert,可以使用git revert —abort命令来停止移除操作,恢复到执行git revert命令之前的状态。
  • 也可以使用git revert —skip命令跳过commit,该条commit将会在历史记录中被删除。这个命令也谨慎使用

工作中常用

  • git revert HEAD:撤销前一次的commit
  • git revert HEAD^ :撤销前前一次的commit

    一次移除多个记录

    在上面的例子中,只是回退了2次,如果需要进行多次回退的话

  • 第一种方式:git revert ,顺序是从后向前,否次会多次冲突。

  • 第二种方式:git revert ,该操作只是回退了5和6,不包括开头的4。并且要注意中间是3个点
  • 第三种方式:git revert ^.., 该操作回退了4、5、6三个提交记录。中间使用2个点。

    revert常用的参数

    -n参数:
    --no-commit
    移除多次提交记录的修改,但是不使用还原后的提交创建新的任何提交,还原只是修改工作树和索引。 ```git

    查看提交历史,此时还包含错误的提交代码

    shuais-MacBook-Pro:revert shuai$ git log —oneline
  • ec2ab45 (HEAD -> master) v4 w
  • 00e34c1 v3 w
  • cb4a3c0 v2
  • 6988773 v1

回退v3和v4的提交

shuais-MacBook-Pro:revert shuai$ git revert -n 00e34c1^..ec2ab45

查看提交历史,v3和v4仍然存在,但是内容已经被恢复掉

shuais-MacBook-Pro:revert shuai$ git log —oneline

  • ec2ab45 (HEAD -> master) v4 w
  • 00e34c1 v3 w
  • cb4a3c0 v2
  • 6988773 v1
    1. <a name="vlW2G"></a>
    2. ##### -m参数:
    3. 移除merge修改的内容。`-m parent-number`全称:`--mainline parent-number`<br />命令: `git revert [-m parent-number] <commit-id>`<br />如果需要还原的提交是merge操作,直接使用`git revert <commit-id>`是不行的,会提示我们
    4. ```git
    5. error:commit... is a merge but no -m option was given.
    6. fatal: revert failed
    因为merge操作有2个分支,而revert不知道要还原哪个分支的提交。
    需要使用 -m 1参数来告诉revert命令哪个是主线,选择主线就还原非主线,选择非主线就还原主线。
    可以使用git show命令查看commit提交记录,如果是普通commit记录,会显示这个commit的id、作者、日期、备注、更改文件的内容。如果是merge记录,则会显示merge的commit-id,备注、日期和merge的主线和合并过来的id。 ```bash commit 00e34c14551df71df0bed4278947f33ba97aca67 Merge: 6988773a8 cb4a3c01de Author: unknown test@163.com Date: Sun Jul 19 11:34:21 2020 +0800

  Merge branch ‘dev’ into main

  1. 上面第二行代码显示merge的记录,说明6988773a8是主线的id,编号就是1cb4a3c01de就是非主线的id,编号是2.需要把合并过来的分支的修改给还原掉,那么就可指定1为主线,还原掉2的提交记录。
  2. <a name="eEP7X"></a>
  3. ### 多个回退实际操作
  4. 假如git [commit](https://so.csdn.net/so/search?q=commit&spm=1001.2101.3001.7020) 链是<br />A -> B -> C -> D<br />如果想把B,C,D都给revert,除了一个一个revert之外,还可以使用range revert<br />git revert B^..D 等价于 git revert A...D
  5. > 用法:
  6. > B^..D代表区间[B,D],包括B也包括D,其中B提交在前,D提交在后,D为起点commit
  7. > A...D 代表一个左开右闭区间(A,D],不包括A,包括D. 其中D为起点commitA为终点commit的下一个commit
  8. > 注意⚠️:都是闭区间时,中间2个点。前开后闭时,中间有3个点。
  9. 这样就把B,C,D都给revert了,变成:<br />A-> B ->C -> D -> D'-> C' -> B'<br />用法就是:<br />git revert BEFORE_COMMIT^..AFTER_COMMIT<br />如果我们想把这三个revert不自动生成三个新的commit,而是用一个commit完成,可以这样:<br />git revert -n BEFORE_COMMIT^..AFTER_COMMIT<br />git commit -m "revert BEFORE_COMMIT to AFTER_COMMIT"
  10. ```git
  11. # 查看提交记录,回退到v2的commit中
  12. shuais-MacBook-Pro:restore shuai$ git alog
  13. * d513690 (HEAD -> master) v5
  14. * 093b730 v4
  15. * 4cff528 v3
  16. * bdaa5d3 v2
  17. * 2688ed0 v1
  18. #下面两种方法,都是要把先有的commit放在前面。
  19. # 第一种方法:两头都是闭区间,2个commit都会包含进去
  20. git revert bdaa5d3^..d513690
  21. # 第二中方法,开头是开区间,不被包含。
  22. git revert 2688ed0...d513690
  23. # 如果一个一个撤销的话,需要把后提交的commit放在前,这样减少冲突.
  24. git revert d513690 093b730 4cff528 bdaa5d3