在 git 中撤消提交的最简单方法是使用 revert 选项:
这会撤销最近的提交。
包括使用 revert 在内,有两种方法可以撤销提交操作:
- git revert: 恢复 git 仓库的先前状态,并将更改反映在 git 日志中;
- git reset:删除上次提交。
还原提交(revert)
如果只是想要撤销一个提交,但是不删除 git 日志,可以使用 git revert 命令。其语法为我们刚刚提到过的:
上述命令中的 可以是用于提交的任何名称,比如可以是在提交的 SHA1(提交时会得到这个值)、标记、引用名称或者其他任何唯一标识提交的东西。
我们来举个例子。首先在 git 中初始化一个文件:
$ git commit -m "init commit"
[master (root-commit) b1adf72] init commit
1 file changed, 3 insertions(+)
create mode 100644 README.md
$ echo "a new line in readme" >> README.md
使用 cat 命令来看一下这个文件的内容:
$ cat README.md
Heading
A readme is useless if it is empty. But this readme is even more useless because it wastes the reader's time.
a new line in readme
然后我使用 git add . 将其添加到暂存区,再然后做一次提交(提交的文本为:a commit that will live on for ever):
$ git commit -m 'a commit that will live on for ever'
[master b731901] a commit that will live on for ever
1 file changed, 1 insertion(+)
这次提交,系统返回给我一个唯一标识(master b731901)。现在我们运行 git revert 并使用该唯一标识,来恢复到上一次提交的状态:
$ git revert master b731901
[master 01c9be7] Revert "a commit that will live on for ever"
1 file changed, 1 deletion(-)
然后我们来看一下 git 日志,检查撤销操作有没有反映在日志中:
$ git log
commit 01c9be75eff7b5ae48c6c35bbb7c63ac1ebc3fcd (HEAD -> master)
Author: Pratham Patel <pratham@itsfoss.com>
Date: Mon Feb 28 21:29:36 2022 +0530
$ git log
commit 01c9be75eff7b5ae48c6c35bbb7c63ac1ebc3fcd (HEAD -> master)
Author: Pratham Patel <pratham@itsfoss.com>
Date: Mon Feb 28 21:29:36 2022 +0530
Revert "a commit that will live on for ever"
This reverts commit b731901deaa30851832c07b7cb7ed535b68d473d.
commit b731901deaa30851832c07b7cb7ed535b68d473d
Author: Pratham Patel <pratham@itsfoss.com>
Date: Mon Feb 28 21:29:12 2022 +0530
a commit that will live on for ever
commit b1adf72e535921ff966ff78f062943b717e78a08
Author: Pratham Patel <pratham@itsfoss.com>
Date: Mon Feb 28 21:20:43 2022 +0530
init commit
上述输出可以看出,git 日志记录了这次撤销,但是 README 文件已经被回复到先前的状态:
$ cat README.md
Heading
A readme is useless if it is empty. But this readme is even more useless because it wastes the reader's time.
删除提交
如果想要彻底恢复错误的提交且不保留日志,可使用 git reset。
git 中的每次提交(commit) 都相当于是仓库的一个快照,另外,在 git 中有一个名为 HEAD 的引用变量--使用 git log 查看日志的时候就能看到。这个 HEAD 用于指向你正在工作的分支中的最近提交。
为了演示,我们首先更改一个文件:
$ git commit -m "init commit"
[master (root-commit) b1adf72] init commit
1 file changed, 3 insertions(+)
create mode 100644 README.md
$ echo "a new line in readme" >> README.md
$ cat README.md
Heading
A readme is useless if it is empty. But this readme is even more useless because it wastes the reader's time.
a new line in readme
然后提交:
$ git add .
$ git commit -m "a commit that i will regret later on"
[master fb58caf] a commit that i will regret later on
1 file changed, 1 insertion(+)
然后使用 git reset 命令来撤销这次提交:
$ git reset --soft HEAD~1
接下来看下 git 日志:
$ git log
commit b1adf72e535921ff966ff78f062943b717e78a08 (HEAD -> master)
Author: Pratham Patel <pratham@itsfoss.com>
Date: Mon Feb 28 21:20:43 2022 +0530
可以看到,我们的上次提交(提交文本 a commit that I will regret later on)已经不见了。
由此可见,这个提交被完全被删除了,因为我将 HEAD 指向移动到了最后一个引用(用HEAD~1表示)。
这个删除操作并没有影响到我们的工作文件 README.md:
$ git status
On branch master
Changes to be committed:
(use "git restore --staged ..." to unstage)
modified: README.md
--soft 标志表示在运行 git reset 的时候修改的是 git 保存的日志。
如果想要将 git 存储库中的内容恢复到先前的状态,可使用 --hard 标志(不过要谨慎使用,确保需要的文件做好备份)。