Git学习(五)--版本回退

转载廖雪峰的官方网站

查看提交版本

现在我们已经学会了修改文件,然后把修改后的文件提交到Git版本库,现在,我们在联系一次,修改readme.txt文件如下。

1
2
Git is a distributed version control system.
Git is free software distributed under the GPL.

然后尝试提交

1
2
3
4
$ git add readme.txt
$ git commit -m "append GPL"
[master d6715a5] append GPL
1 file changed, 1 insertion(+), 1 deletion(-)

​ 像这样,你不断的对文件进行修改,然后不断的提交修改到版本库中,这个就像大家玩RPG游戏似的,每通关一关就会自动将游戏状态存盘,如果某一关没有过去,就可以选择读取上一关的状态。Git也是一样,每当你觉得文件修改到一定程度的时候,就可以保存一个“快照”,这个“快照”在Git中被称为commit。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,然后继续工作,而不是把几个月的工作成果全部丢失。
​ 现在,我们回顾一下readme.txt文件一共又几个版本被提交到Git仓库中
版本1:wrote a readme file

1
2
Git is a version control system.
Git is free software.

版本2:add distributed

1
2
Git is a distributed version control system.
Git is free software.

版本3:append GPL

1
2
Git is a distributed version control system.
Git is free software distributed under the GPL.

当然,在实际工作中,我们不可能记得每次修改的内容,不然要版本控制系统干什么。版本控制系统中肯定含有命令可以告诉我们历史记录,在Git中,我们用git log命令查看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
git log
commit d6715a56b8e891b6e3894b4e2662fa67340f562a
Author: wuqinghua <zffwqh@126.com>
Date: Tue Sep 19 13:00:16 2017 +0800
append GPL
commit bf483385124eb7e4634cbdc1a293eeba19c17818
Author: wuqinghua <zffwqh@126.com>
Date: Tue Sep 19 12:49:41 2017 +0800
add distributed
commit ead05c0c5508b9a3d7e7e36896e8524c5c7fae47
Author: wuqinghua <zffwqh@126.com>
Date: Tue Sep 19 11:26:34 2017 +0800
wrote a readme file

git log命令显示从最近到最远的提交日志,我们可以看到3次提交,最近一次是append GPL,上一次是add distributed,最早一次是wrote a readme file
​ 如果嫌输出的信息太多,看不清晰,可以尝试添加上--pretty=oneline参数:

1
2
3
4
$ git log --pretty=oneline
d6715a56b8e891b6e3894b4e2662fa67340f562a append GPL
bf483385124eb7e4634cbdc1a293eeba19c17818 add distributed
ead05c0c5508b9a3d7e7e36896e8524c5c7fae47 wrote a readme file

PS:日志中的前面的一串字符串为提交的id commit id

进行版本回退

​ 现在我们就可以开启时光穿梭机了,准备将readme.txt回退到上个版本,也就是回退到add distribute的那个版本,怎么做呢?
​ 首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是d6715a...67340f562a(我的提交id肯定和你的不一样),上一个版本就是HEAD^,上上个版本就是HEAD^^,当然往上100个版本写上100个^不容易写出了,所以可以写成HEAD-100
​ 现在,我们要把当前版本append GPL回退到add distributed,就可以使用git reset命令

1
2
$ git reset --hard HEAD^
HEAD is now at bf48338 add distributed

--hard参数的含义我们后面会讲,现在先使用
现在看看readme.txt的内容是不是回退到上个版本的内容了,也就是是否为add distributed

1
2
3
cat readme.txt
Git is a distributed version control system.
Git is free software.

还可以恢复到上个版本wrote a readme file,我们先使用git log在看看提交的记录

1
2
3
4
5
6
7
8
9
10
11
12
$ git log
commit bf483385124eb7e4634cbdc1a293eeba19c17818
Author: wuqinghua <zffwqh@126.com>
Date: Tue Sep 19 12:49:41 2017 +0800
add distributed
commit ead05c0c5508b9a3d7e7e36896e8524c5c7fae47
Author: wuqinghua <zffwqh@126.com>
Date: Tue Sep 19 11:26:34 2017 +0800
wrote a readme file

最新的那个append GPL已经看不到,这个就好比,21世纪的人穿梭到19世纪,回不去了,怎么版?
办法其实还是存在的,比如如果你的终端没有关闭的话,可以在上面找到那个append GPLcommit idd6715a56b8e891b6e3894b4e2662fa67340f562a,于是就可以指定回到未来的某个版本。

1
2
$ git reset --hard d6715a56b8e
HEAD is now at d6715a5 append GPL

​ 版本号没必要写全,前几位就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。
​ 这个时候再查看一下文件。

1
2
3
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.

​ 果然,又回到了add GPL版本
​ Git的版本回退速度非常的快,因为在Git中含有一个指向HEAD指针,当你回退版本的时候,Git仅仅是将HEAD指向append GPL

修改为指向add distributed

然后顺便将工作区的文件更新了。所以你让HEAD指向哪个版本,你就把当前的版本定位在哪里。

但是如果,你回退到哪个版本之后,关掉了电脑,第二天后悔了,想要恢复怎么办?找不到commit id了。
在Git中总是有方式决解的。当你用git reset --hard HEAD^回退到add distributed版本时,再想恢复到add GPL就必须找到add GPLcommit id。在Git中提供了一个命令git reflog用来记录你的每一次命令:

1
2
3
4
5
6
$ git reflog
d6715a5 HEAD@{0}: reset: moving to d6715a56b8e
bf48338 HEAD@{1}: reset: moving to HEAD^
d6715a5 HEAD@{2}: commit: append GPL
bf48338 HEAD@{3}: commit: add distributed
ead05c0 HEAD@{4}: commit (initial): wrote a readme file

可以看到第三行显示就为append GPLcommit id,现在你又可以使用git reset命令进行版本穿梭了

小结

现在总结一下:

  • HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
  • 穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。
  • 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本