版本回退
之前我们也提到过,Git 能够管理⽂件的历史版本,这也是版本控制器重要的能⼒。如果有⼀天你发现
之前前的⼯作做的出现了很⼤的问题,需要在某个特定的历史版本重新开始,这个时候,就需要版本回退的功能了。
执⾏ git reset 命令⽤于回退版本,可以指定退回某⼀次提交的版本。要解释⼀下“回退”本质是要将版本库中的内容进⾏回退,⼯作区或暂存区是否回退由命令参数决定:
git reset 命令语法格式为: git reset [–soft | --mixed | --hard] [HEAD]
• --mixed 为默认选项,使⽤时可以不⽤带该参数。该参数将暂存区的内容退回为指定提交版本内容,⼯作区⽂件保持不变。
• --soft 参数对于⼯作区和暂存区的内容都不变,只是将版本库回退到某个指定版本。
• --hard 参数将暂存区与⼯作区都退回到指定版本。切记⼯作区有未提交的代码时不要⽤这个命令,因为⼯作区会回滚,你没有提交的代码就再也找不回了,所以使⽤该参数前⼀定要慎重。
• HEAD 说明:
◦ 可直接写成 commit id,表⽰指定退回的版本
◦ HEAD 表⽰当前版本
◦ HEAD^ 上⼀个版本
◦ HEAD^^ 上上⼀个版本
◦ 以此类推…
• 可以使⽤ 〜数字表⽰:
◦ HEAD~0 表⽰当前版本
◦ HEAD~1 上⼀个版本
◦ HEAD^2 上上⼀个版本
◦ 以此类推…
为了便于表述,⽅便测试回退功能,我们先做⼀些准备⼯作:更新3个版本的 ReadMe,并分别进⾏3次提交,如下所⽰:
1 # 第⼀次修改提交
2 hyb@139-159-150-152:~/gitcode$ cat ReadMe
3 hello bit
4 hello git
5 hello world
6 hello version1
7 hyb@139-159-150-152:~/gitcode$ git add ReadMe
8 hyb@139-159-150-152:~/gitcode$ git commit -m"add version1"
9 [master cff9d1e] add version1
10 1 file changed, 1 insertion(+)
11
12 # 第⼆次修改提交
13 hyb@139-159-150-152:~/gitcode$ cat ReadMe
14 hello bit
15 hello git
16 hello world
17 hello version1
18 hello version2
19 hyb@139-159-150-152:~/gitcode$ git add ReadMe
20 hyb@139-159-150-152:~/gitcode$ git commit -m"add version2"
21 1 file changed, 1 insertion(+)
22
23 # 第三次修改提交
24 hyb@139-159-150-152:~/gitcode$ cat ReadMe
25 hello bit
26 hello git
27 hello world
28 hello version1
29 hello version2
30 hello version3
31 hyb@139-159-150-152:~/gitcode$ git add ReadMe
32 hyb@139-159-150-152:~/gitcode$ git commit -m"add version3"
33 [master d95c13f] add version3
34 1 file changed, 1 insertion(+)
35
36 # 查看历史提交记录
37 hyb@139-159-150-152:~/gitcode$ git log --pretty=oneline
38 d95c13ffc878a55a25a3d04e22abfc7d2e3e1383 (HEAD -> master) add version3
39 14c12c32464d6ead7159f5c24e786ce450c899dd add version2
40 cff9d1e019333318156f8c7d356a78c9e49a6e7b add version1
41 ...
现在,如果我们在提交完 version3 后, 发现 version 3 编写错误,想回退到 version2,重新基于version 2 开始编写。由于我们在这⾥希望的是将⼯作区的内容也回退到 version 2 版本,所以需要⽤到 --hard 参数,⽰例如下:
1 hyb@139-159-150-152:~/gitcode$ git log --pretty=oneline
2 d95c13ffc878a55a25a3d04e22abfc7d2e3e1383 (HEAD -> master) add version3
3 14c12c32464d6ead7159f5c24e786ce450c899dd add version2
4 cff9d1e019333318156f8c7d356a78c9e49a6e7b add version1
5 ...
6 hyb@139-159-150-152:~/gitcode$ git reset --hard
14c12c32464d6ead7159f5c24e786ce450c899dd
7 HEAD is now at 14c12c3 add version2
8 hyb@139-159-150-152:~/gitcode$ cat ReadMe
9 hello bit
10 hello git
11 hello world
12 hello version1
13 hello version2
我们惊奇的发现,此时 ReadMe ⽂件的内容,已经回退到 version2 了!,当前,我们再次⽤ git log 查看⼀下提交⽇志,发现 HEAD 指向了version2,如下所⽰:
1 hyb@139-159-150-152:~/gitcode$ git log --pretty=oneline
2 14c12c32464d6ead7159f5c24e786ce450c899dd (HEAD -> master) add version2
3 cff9d1e019333318156f8c7d356a78c9e49a6e7b add version1
4 ...
到这⾥⼀般回退功能就演⽰完了,但现在如果我后悔了,想再回到 version 3 怎么办?我们可以继续使⽤ git reset 命令,回退到 version 3 版本,但我们必须要拿到 version 3 的 commit id 去指定回退的版本。
但我们看到了 git log 并不能打印出 version 3 的 commit id ,运⽓好的话我们可以从终端上去找找之前的记录,运⽓不好的话 commit id 已经被我们搞丢了=。=
Git 还提供了⼀个 git reflog 命令能补救⼀下,该命令⽤来记录本地的每⼀次命令。
1 hyb@139-159-150-152:~/gitcode$ git reflog
2 14c12c3 (HEAD -> master) HEAD@{0}: reset: moving to
14c12c32464d6ead7159f5c24e786ce450c899dd
3 d95c13f HEAD@{1}: commit: add version3
4 14c12c3 (HEAD -> master) HEAD@{2}: commit: add version2
5 cff9d1e HEAD@{3}: commit: add version1
6 94da695 HEAD@{4}: commit: add modify ReadMe file
7 23807c5 HEAD@{5}: commit: add 3 files
8 c614289 HEAD@{6}: commit (initial): commit my first file
这样,你就可以很⽅便的找到你的所有操作记录了,但 d95c13f 这个是啥东西?这个是 version 3 的 commit id 的部分。没错,Git 版本回退的时候,也可以使⽤部分 commit id 来代表⽬标版本。⽰例如下:
1 # 回退到v3
2 hyb@139-159-150-152:~/gitcode$ git reset --hard d95c13f
3 HEAD is now at d95c13f add version3
4
5 # 查看⼯作区
6 hyb@139-159-150-152:~/gitcode$ cat ReadMe
7 hello bit
8 hello git
9 hello world
10 hello version1
11 hello version2
12 hello version3
13
14 # 查看log
15 hyb@139-159-150-152:~/gitcode$ git log --pretty=oneline
16 d95c13ffc878a55a25a3d04e22abfc7d2e3e1383 (HEAD -> master) add version3
17 14c12c32464d6ead7159f5c24e786ce450c899dd add version2
18 cff9d1e019333318156f8c7d356a78c9e49a6e7b add version1
19 94da6950d27e623c0368b22f1ffc4bff761b5b00 add modify ReadMe file
20 23807c536969cd886c4fb624b997ca575756eed6 add 3 files
21 c61428926f3853d4ec6dde904415b0e6c1dabcc6 commit my first file
可往往是理想很丰满,现实很⻣感。在实际开发中,由于⻓时间的开发了,导致 commit id 早就找不到了,可突然某⼀天,我⼜想回退到 version3,那该如何操作呢?貌似现在不可能了。。。
值得说的是,Git 的版本回退速度⾮常快,因为 Git 在内部有个指向当前分⽀(此处是master)的HEAD 指针, refs/heads/master ⽂件⾥保存当前 master 分⽀的最新 commit id 。当我们在回退版本的时候,Git 仅仅是给 refs/heads/master 中存储⼀个特定的version,可以简单理解成如下⽰意图:
因为 Git 在内部有个指向当前分⽀(此处是master)的HEAD 指针, refs/heads/master ⽂件⾥保存当前 master 分⽀的最新 commit id 。当我们在回退版本的时候,Git 仅仅是给 refs/heads/master 中存储⼀个特定的version,可以简单理解成如下⽰意图: