12-git reset 版本回退
- 官网地址:https://git-scm.com/docs
git reset
官网地址:https://git-scm.com/docs/git-reset
1、知识前提:git 重要的三个工作区域
- 工作区(Working Directory):写代码的目录。就是项目代码存放的目录。
- 暂存区(index/stage):工作区与版本库之间的缓冲地带。用
git add
添加文件,实际上是把文件修改添加到暂存区。 - 版本库(仓库区):
git commit
提交更改,实际上是把暂存区的所有内容全部提交到当前分支,查看记录git log
。
2、git reset
版本回退
git reset
命令用于回退版本,可以指定退回某一次提交的版本。
语法
1 |
|
2.1 –mixed
默认参数。保留工作目录,将所有修改放入到工作区
示例:
1 |
|
作用:reset 默认使用 --mixed
参数。用于重置 暂存区和版本区 的文件。保留工作目录,并且清空暂存区中未提交的修改。也就是说,工作目录的修改、暂存区的未提交的内容以及由 reset 所导致的新的文件差异,都会被放进工作目录。简而言之,就是把所有差异都混合(mixed)放在工作目录中。
- 版本区:移动 HEAD 指针指向
HEAD 参数指定的 commit_id
,文件内容恢复到HEAD 参数指定的 commit_id
提交时的内容。HEAD 参数指定的 commit_id
之后变化的内容放到工作区,变成未 add 状态。 - 暂存区:文件内容与
HEAD 指定的 commit_id
提交时的数据保持一致。已 add 未 commit 的内容放到工作区,变成未 add 状态。 - 工作区:文件内容保持不变,但是状态有所变更。工作目录的修改、暂存区的未提交的内容以及由 reset 所导致的新的文件差异,都会被放进工作目录。
使用场景:
- 使用
reset --mixed
之后,执行git add
将这些改变过的文件內容加入 暂存区(index) 中,再执行git commit
将暂存区中的內容提交至仓库中,和reset --soft
一样可以达到合并 commit 节点的效果。 - 用于当发现 add 错了,执行
git reset HEAD
来重置暂存区(index)的文件。
测试:
第一次提交文件内容
1
add 1
第二次提交文件内容
1
2add 1
add 2修改文件
1
2
3add 1
add 2
add 3执行
git reset
,然后执行git status
、git diff
、git diff --cached
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29fenglepeng@PC00110544 MINGW64 /d/git/test (master)
$ git reset a19a6f9917
fenglepeng@PC00110544 MINGW64 /d/git/test (master)
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a.txt
no changes added to commit (use "git add" and/or "git commit -a")
fenglepeng@PC00110544 MINGW64 /d/git/test (master)
$ git diff
diff --git a/a.txt b/a.txt
index b9ff64e..3bf8a10 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1,3 @@
add 1
+add 2
+add 3
\ No newline at end of file
fenglepeng@PC00110544 MINGW64 /d/git/test (master)
$ git diff --cached
2.2 -soft
保留工作目录,并把重置 HEAD 所带来的新的差异放进暂存区。
作用:在重置版本库的时候,保留工作目录和暂存区中的内容,并把重置版本库所带来的新的差异放进暂存区。也就说是说,工作目录的内容不受影响,而暂存区中已经 commit 的内容变成已 add 的状态
- 版本库:移动当前 Head 指针,指向
HEAD 参数指定的 commit_id
,文件内容恢复到HEAD 参数指定的 commit_id
提交时的内容。HEAD 参数指定的 commit_id
之后的内容放到 暂存区,变成未 commit 状态。 - 暂存区:文件内容与
HEAD 指定的 commit_id
提交时的数据保持一致。重置版本库所带来的新的差异放进暂存区。 - 工作区:文件内容保持不变,状态也不变,修改内容和删除内容还是未 add 的状态。
使用场景:
- 使用
reset --soft
之后,commit_id
之后提交的内容会被放入暂存区(index)中,此时可以直接执行commit,将commit_id
之后的提交作为一个 commit 来统一进行提交,减少不必要的log记录
测试:
第一次提交文件内容
1
add 1
第二次提交文件内容
1
2add 1
add 2修改文件
1
2
3add 1
add 2
add 3执行
git reset
,然后执行git status
、git diff
、git diff --cached
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40fenglepeng@PC00110544 MINGW64 /d/git/test (master)
$ git reset --soft 2073078181eeea97951a2b1c2460b664b9ab2e25
fenglepeng@PC00110544 MINGW64 /d/git/test (master)
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: a.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a.txt
fenglepeng@PC00110544 MINGW64 /d/git/test (master)
$ git diff
diff --git a/a.txt b/a.txt
index 9237eb7..3bf8a10 100644
--- a/a.txt
+++ b/a.txt
@@ -1,2 +1,3 @@
add 1
add 2
+add 3
\ No newline at end of file
fenglepeng@PC00110544 MINGW64 /d/git/test (master)
$ git diff --cached
diff --git a/a.txt b/a.txt
index 6bf3f98..9237eb7 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1,2 @@
add 1
+add 2
\ No newline at end of file
2.3 –hard
撤销工作区中所有未提交的修改内容,
作用:在重置版本的同时,重置暂存区和工作目录里的内容。也就说,就是在暂存区中你没有 commit 的修改会被全部擦掉,在工作区中你没有 add 的修改也被全部擦掉。
- 版本库:移动当前 Head 指针,指向
HEAD 参数指定的 commit_id
,文件内容恢复到HEAD 参数指定的 commit_id
提交时的内容。HEAD 参数指定的 commit_id
之后的内容丢失。 - 暂存区与工作区:都回到指定版本,并删除所有未 commit 和未 add 的内容。
- 最危险的操作,容易造成丢失
使用场景:
使用
git reset --hard HEAD
来强制恢复 git 管理的文件夹的內容及状态;版本回滚。
但是这种操作存在一个问题,服务器上的代码虽然被还原了,但假如有多个人在这个分支上开发,他们本地的版本依然是比服务器上的版本高的,所以,别人再重新提交(push)代码的话,你撤销的操作又会被重新,你上面的操作也就白操作了。
解决办法是,让别人把本地的分支先删掉,然后重新从服务器上拉取分支,或者你在对方提交完所有本地代码之后对方没有再进行修改代码,这个时候你提交了,发现你提交的有问题,再进行reset操作,然后让对方拉取(pull)最新的代码也ok,最主要的就是对方本地没有你要reset的代码即可误删恢复。如果回滚代码之后发现复制错了
commit_id
,或者误删了某次 commit 记录,也可以通过下方代码恢复:1
2git relog // 复制要恢复操作的前面的 hash 值
git reset --hard hash // 将 hash 换成要恢复的历史记录的 hash 值