Fork me on GitHub

Git 撤销与回滚

git 工作区(Working Directory)、暂存区(Stage)和历史记录区(History)的关系

Git 撤销与回滚

Git 撤销与回滚


撤销工作区:

未添加到暂存区的撤销,还没有git add

1
use 'git checkout -- <file>...' to discard changes in working directory

一次性撤销多个文件:

1
git checkout -- <folder>


撤销暂存区:

git add添加到暂存区的,还没有git commit

1
use "git reset HEAD <file>..." to unstage

一次性将所有暂存区文件撤销:

1
git reset HEAD

举例:
新增index.js,并git add添加到暂存区:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.

Changes to be committed:
(use 'git reset HEAD <file>...' to unstage)

modified: index.js

Changes not staged for commit:
(use 'git add <file>...' to update what will be committed)
(use 'git checkout -- <file>...' to discard changes in working directory)

modified: index.js

reset撤销清空暂存区:

1
2
3
$ git reset HEAD index.js
Unstaged changes after reset:
M index.js

再查看:

1
2
3
4
5
6
7
8
9
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.

Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: index.js

再用git checkout清空工作区,之后再查看:

1
2
3
4
5
6
7
$ git checkout -- index.js

$ git status
On branch dev
Your branch is up to date with 'origin/dev'.

nothing to commit, working tree clean

Git 撤销与回滚


撤销历史区:

如果commit提交后想撤销,这就需要revert命令。git revert命令是撤销某次操作,此次操作之前和之后的commithistory都会保留,并且把这次撤销作为一次最新的提交。

1
2
git revert commit_id
git revert HEAD 删除最后一次提交

先提交修改然后再用git log查看提交记录。

Git 撤销与回滚

1
2
3
4
5
6
$ git log
commit 707ffbee6b5b2f7eb7ff42e0a12992aaab43140c (HEAD -> dev, origin/dev)
Author: lzx <[email protected]>
Date: Tue Oct 27 09:19:54 2020 +0800

third commit on dev

然后使用git revert后面跟上git提交的commit_id

1
2
3
4
5
6
7
8
9
10
11
12
13
14
git revert 707ffbee6b5b2f7eb7ff42e0a12992aaab43140c

Revert "third commit on dev"

This reverts commit 707ffbee6b5b2f7eb7ff42e0a12992aaab43140c.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch dev
# Your branch is up to date with 'origin/dev'.
#
# Changes to be committed:
# modified: index.js

修改后输入esc退出编辑模式,输入:wq保存编辑并退出。

1
2
3
$ git revert 707ffbee6b5b2f7eb7ff42e0a12992aaab43140c
[dev a137703] Revert "third commit on dev"
1 file changed, 1 insertion(+), 3 deletions(-)

Git 撤销与回滚

之后再推送到远端更新远程仓库代码,修改的文件就撤销了。

用 source tree 操作:

回滚提交:

Git 撤销与回滚

回滚生成新的提交:

Git 撤销与回滚

提交到远程仓库:

Git 撤销与回滚


Git Reset 三种模式:

Git 撤销与回滚

Git 撤销与回滚

reset –soft commit_id:
保留本地working directory工作区,并把重置HEAD所带来的新的差异放进本地stage暂存区

Git 撤销与回滚

Git 撤销与回滚

reset –mixed commit_id:
保留本地working directory工作区,并清空本地stage暂存区。
也就是说,工作目录的修改、暂存区的内容以及由reset所导致的新的文件差异,都会被放进工作目录。简而言之,就是把所有差异都混合(mixed)放在工作目录中。

Git 撤销与回滚

Git 撤销与回滚

reset –hard commit_id:
强制将本地stage暂存区和本地working directory工作区都同步到你指定的提交。
会在重置HEADbranch的同时,重置stage区和working directory里的内容。你的暂存区和工作目录里的内容会被完全重置为和HEAD的新位置相同的内容。没有commit的修改会被全部擦掉。
可以回退到某次提交 A,A 之后的提交都会回滚,覆盖是不可逆的,谨慎使用。

重置前:

Git 撤销与回滚

Git 撤销与回滚

重置后:

Git 撤销与回滚

Git 撤销与回滚

之后强行推送更新远程仓库:

1
2
3
4
$ git push origin dev -f
Total 0 (delta 0), reused 0 (delta 0)
To github.com:luanzhuxian/git-examples.git
+ def670f...707ffbe dev -> dev (forced update)

Git 撤销与回滚

reset这个指令虽然可以用来撤销commit,但它的实质行为并不是撤销,而是移动HEAD,重置HEAD以及它所指向的branch的位置的。
reset --hard之所以起到了撤销commit的效果,是因为它把HEAD和它所指向的branch一起移动到了当前commit的父commit上,从而起到了撤销的效果。

Git 撤销与回滚