目录
git操作(2)
1.版本回退
git能够管理文件的历史版本,这也是版本控制器的重要能力,因此,git也提供了版本回退这样的功能。
执行git reset进行回退版本,可以指定退回某一次提交的版本。回退是为了将版本库中的内容回退,而工作区和暂存区中的内容是否要回退由命令选项决定。
cpp
git reset --mixed/--soft/--hard HEAD
- --mixed为默认选项,使用时可以不带命令参数,该命令将版本库和暂存区的内容回退到指定的提交版本,工作区的内容保持不变。
- --soft将版本库中的内容回退到指定的提交版本,暂存区和工作区的内容保持不变。
- --hard将版本库、暂存区、工作区的内容都回退到指定的提交版本,因此,这个命令参数要慎用。
- HEAD说明:
1.可以使用commit id表示指定回退的版本
2.可以使用^表示:
HEAD表示当前版本
HEAD^表示上个版本
HEAD^^表示上上个版本
3.可以使用~数字表示:
HEAD~0表示当前版本
HEAD~1表示上个版本
HEAD~2表示上上个版本
|---------|-----|-----|-----|
| | 工作区 | 暂存区 | 版本库 |
| --soft | 不变 | 不变 | 回退 |
| --mixed | 不变 | 回退 | 回退 |
| --hard | 回退 | 回退 | 回退 |
为了便于表述,方便测试回退功能,我们先更新3个版本的ReadMe,提交三次,分别表示3个版本。
cpp
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
现在,如果我们在提交完version3以后,发现编写错误,想要回退到version2重新编写,这里希望是工作区回退到上一个版本,因此使用 --hard命令参数。
cpp
hyb@139-159-150-152:~/gitcode$ git reset --hard 14c12c32464d6ead7159f5c24e786ce4
HEAD is now at 14c12c3 add version2
hyb@139-159-150-152:~/gitcode$ cat ReadMe
hello bit
hello git
hello world
hello version1
hello version2
查看日志发现已经回退到上一个版本了。
cpp
1 hyb@139-159-150-152:~/gitcode$ git log --pretty=oneline
2 14c12c32464d6ead7159f5c24e786ce450c899dd (HEAD -> master) add version2
3 cff9d1e019333318156f8c7d356a78c9e49a6e7b add version1
那么此时再想回退到version3怎么办,如果能轻易获取到提交version3版本的commit id,同样使用git reset命令也可以回退到version 3。
cpp
git reset --hard "version3的commit id"
或者可以使用命令git reflog查看本机的提交记录。
cpp
1 hyb@139-159-150-152:~/gitcode$ git reflog
2 14c12c3 (HEAD -> master) HEAD@{0}: reset: moving to 14c12c32464d6ead7159f5c24e78
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
这里需要注意的是,该命令结果显示的commit id仅仅是commit id的一部分,即使如此,也可以用来回退版本。
cpp
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的查找并没有想象中那么轻而易举。
在版本回退的操作过程中,速度是非常快的,因此底层并不是删除代码或新增代码,而是版本控制。在git内部有一个指向当前分支(这里是master)的指针HEAD,refs/heads/master里面保存这当前分支master的最新一次commit id,当我们进行版本回退时,git仅仅是修改refs/heads/master里面的commit id。
2.撤销修改
如果我们当前正在工作区写代码,想要回退到刚开始的状态,要怎么做呢。当然,如果仅仅是有2、3行的变化我们可以直接删除,但是如果有多个文件发生了大量改动,有什么命令可以完成我们的需求呢?
- 情况1:仅仅是工作区被修改,没有add
cpp
//使用checkout,当前场景必须使用 -- ,否则,就是另一种用法
git checkout -- 文件名
cpp
1 //向ReadMe中新增⼀⾏代码
2 hyb@139-159-150-152:~/gitcode$ vim ReadMe
3 hyb@139-159-150-152:~/gitcode$ cat ReadMe
4 hello bit
5 hello git
6 hello world
7 hello version1
8 hello version2
9 hello version3
10 This piece of code is like shit //新增代码
11
12 //恢复到上⼀次 add 或 commit
13 hyb@139-159-150-152:~/gitcode$ git checkout -- ReadMe
14 hyb@139-159-150-152:~/gitcode$ cat ReadMe
15 hello bit
16 hello git
17 hello world
18 hello version1
19 hello version2
20 hello version3
21
- 情况2:已经add,但没有commit
这种情况可以分成2步来解决,先使用git reset --mixed,将暂存区的内容回退到当前版本。再将工作区的内容回退,和情况1的解决方法相同。
第一步:
cpp
1 //--mixed 是默认参数,使⽤时可以省略
2 hyb@139-159-150-152:~/gitcode$ git reset HEAD ReadMe
3 Unstaged changes after reset:
4 M ReadMe
第二步:
cpp
1 hyb@139-159-150-152:~/gitcode$ git checkout -- ReadMe
2 hyb@139-159-150-152:~/gitcode$ git status
3 On branch master
4 nothing to commit, working tree clean
5 hyb@139-159-150-152:~/gitcode$ cat ReadMe
6 hello bit
7 hello git
8 hello world
9 hello version1
10 hello version2
11 hello version3
- 情况3:已经commit
cpp
//使用git reset --hard
git reset --hard HEAD^
不过这种情况只适用没有将本地仓库push到远程仓库的情况。
3.删除文件
删除文件也是一种修改。如果我们像下面这样删除文件file5:
cpp
1 hyb@139-159-150-152:~/gitcode$ ls
2 file1 file2 file3 file4 file5 ReadMe
3 hyb@139-159-150-152:~/gitcode$ rm file5
这样的删除仅仅是在工作区删除了文件,被记录为一次修改,git status会显示这种修改。
cpp
1 hyb@139-159-150-152:~/gitcode$ git status
2 On branch master
3 Changes not staged for commit:
4 (use "git add/rm <file>..." to update what will be committed)
5 (use "git restore <file>..." to discard changes in working directory)
6 deleted: file5
7
8 no changes added to commit (use "git add" and/or "git commit -a")
在这时,一般是可能发生了两种情况:
- 确实要在版本库中删除该文件
- 误删
如果是误删,可以看成是工作区的一次修改要恢复到原来的状态。
cpp
1 hyb@139-159-150-152:~/gitcode$ git checkout -- file5
2 hyb@139-159-150-152:~/gitcode$ ls
3 file1 file2 file3 file4 file5 ReadMe
而如果是真的要从版本库中删除该文件,就要使用git rm命令将文件从工作区和暂存区中删除,再做一次提交。
cpp
1 hyb@139-159-150-152:~/gitcode$ git rm file5
2 rm 'file5'
3 hyb@139-159-150-152:~/gitcode$ git status
4 On branch master
5 Changes to be committed:
6 (use "git restore --staged <file>..." to unstage)
7 deleted: file5
8
9 hyb@139-159-150-152:~/gitcode$ git commit -m"deleted file5"
10 [master 5476bde] deleted file5
11 1 file changed, 0 insertions(+), 0 deletions(-)
12 delete mode 100644 file5
13 hyb@139-159-150-152:~/gitcode$ git status
14 On branch master
15 nothing to commit, working tree clean