撤销与恢复

给我一杯忘情水,换我一生不流泪

撤销操作

版本回退

有时我们进行了错误的commit,但是还未push到远程分支,可以使用git reset撤销commit。git reset命令用于回退版本或某一个特定文件,其参数如下:

  • --soft:回退到某个版本,只回退commit信息,但是
  • --hard
1
2
3
$ git reset --soft HEAD~1               # 回退所有内容到上一个版本  
$ git reset --soft HEAD~1 hello.php # 回退 hello.php 文件的版本到上一个版本
$ git reset --soft efc793226 # 回退到指定版本

现在我们以实际的例子展示一下soft和hard的区别,假设我们有一个仓库,当前commit为efc793226d,然后添加了一个test.txt文件,再次commit,现在使用git log得到的版本信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
$ git log
commit b3a357e3bc2exxxxxxxxxxxxxxxxxxxxxxxx (HEAD -> master)
Author: sqduan <xxxx.edu.cn>
Date: Tue Aug 24 22:48:39 2021 +0800

add test1.txt

commit efc793226d2e5b98b54735b70d08d37d1cd0973e
Author: sqduan <sqduan@mail.ustc.edu.cn>
Date: Tue Aug 24 22:48:08 2021 +0800

add a readme

假设我们不想要这次操作了,需要回退到上一个版本,如果执行软回退命令git reset --soft HEAD~1,那么结果如下:

1
2
3
4
5
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: test1.txt

可以看到我们提交的commit已经被撤回了,但是已经add的文件还在,我们可以再次进行commit,重新提交,得到结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
$ git log
commit c3a154aea8fxxxxxxxxxxxxx (HEAD -> master)
Author: sqduan <sqduan@mail.ustc.edu.cn>
Date: Tue Aug 24 22:57:53 2021 +0800

add new file

commit efc793226d2e5b98b54735b70d08d37d1cd0973e
Author: sqduan <sqduan@mail.ustc.edu.cn>
Date: Tue Aug 24 22:48:08 2021 +0800

add a readme

现在我们进行hard回退,回退完后结果如下:

1
2
3
4
5
6
7
8
asus@LAPTOP-961FE4JM MINGW64 /f/Code/Projects/GitTest (master)
$ git reset --hard HEAD~1
HEAD is now at efc7932 add a readme

asus@LAPTOP-961FE4JM MINGW64 /f/Code/Projects/GitTest (master)
$ git status
On branch master
nothing to commit, working tree clean

可以看到此时的状态是nothing to commit,而查看我们的本地代码仓,发现test1.txt也没了,所以hard指令会撤销工作区中所有未提交的修改内容,并将暂存区和工作区同时回退至前面的版本,删除信息提交。这个命令很危险,谨慎使用

恢复操作

版本恢复

以上面的版本回退过程为例,假如我们执行了git reset --hard HEAD~1回到了以前的分支,而现在需要恢复到现在的分支,同样地,我们可以使用reset进行操作,首先我们需要查看对应的操作记录:

1
git reflog

在上面的例子中,我们的操作记录如下:

1
2
3
4
5
6
$ git reflog
efc7932 (HEAD -> master) HEAD@{0}: reset: moving to HEAD~1
c3a154a HEAD@{1}: commit: add new file
efc7932 (HEAD -> master) HEAD@{2}: reset: moving to HEAD~1
b3a357e HEAD@{3}: commit: add test1.txt
efc7932 (HEAD -> master) HEAD@{4}: commit (initial): add a readme

reflog不是记录commit号,而是记录了几乎所有的操作,因此我们可以很方便地进行回退,我们需要回到最后一次reset之前的commit,即HEAD@{1},那么只需要reset到对应的commit号即可:

1
git reset c3a154a

回退之后再看一下git status,发现虽然commit回退了,但是我们的本地文件并没有恢复,而且这个删掉的文件也作为了一个需要提交的修改,这也说明使用--hard是非常危险的,即使commit能回退,工作区中的内容也无法恢复。

1
2
3
4
5
6
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: test1.txt

参考文献

0%