十一、Git版本回退
你在Git版本库中工作了很长时间,做了很多修改和提交。但是,有一天你发现你在错误的道路上走了很长时间,你想回到历史的某一次版本,怎么办?
别怕,只要你提交到Git版本库了,所有的操作都是有记录并可恢复的,你随时可以回退到某个历史状态。
先用git log命令查看版本库中的提交历史:
$ git log
commit 1d7505ff878281db3dba47c261e48efc84c0d939 (HEAD -> master)
Author: admin <admin@com>
Date: Thu Sep 2 15:08:25 2021 +0800
添加设计文档2
commit aeb65f4a813ec759c1bd886b196080ec06835414
Author: admin <admin@com>
Date: Sun Aug 29 16:59:20 2021 +0800
添加需求文档
commit 2c97086779fc3d4de014689f296d77f8ea4a865f
Author: admin <admin@com>
Date: Sun Aug 29 13:57:40 2021 +0800
修改README.txt文件
commit a235818c40c14a444a0299c1af05e9f774287dce
Author: admin <admin@com>
Date: Sun Aug 29 10:31:32 2021 +0800
git log命令显示从最近到最远的提交日志,这里只列出了最近的3次提交。
如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数:
$ git log --pretty=oneline
1d7505ff878281db3dba47c261e48efc84c0d939 (HEAD -> master) 添加设计文档2
aeb65f4a813ec759c1bd886b196080ec06835414 添加需求文档
2c97086779fc3d4de014689f296d77f8ea4a865f 修改README.txt文件
a235818c40c14a444a0299c1af05e9f774287dce 添加readme文件
关于git log命令的更多用法,可以参考这篇文章:查看Git版本库的提交历史。
每提交一个新版本,实际上Git就会把它们自动串成一条时间线。如果使用可视化工具查看Git历史,就可以更清楚地看到提交历史的时间线:
现在我们想回到“添加需求文档”所对应的那个版本,怎么做呢?
首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交1094adb…(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。
现在,我们要把当前版本“添加设计文档2”回退到上一个版本“添加需求文档”,就可以使用git reset命令:
$ git reset --hard HEAD^
HEAD is now at aeb65f4 添加需求文档
其中,--hard参数是表示强制回退版本,直接丢弃工作目录中的所有修改。
这时,我们再执行git log命令来查看版本库的提交历史:
$ git log --pretty=oneline
aeb65f4a813ec759c1bd886b196080ec06835414 (HEAD -> master) 添加需求文档
2c97086779fc3d4de014689f296d77f8ea4a865f 修改README.txt文件
a235818c40c14a444a0299c1af05e9f774287dce 添加readme文件
果然,我们已经回退到“添加需求文档”所对应的版本状态了,而最新的提交“添加设计文档2”已经看不到了。好比你从21世纪坐时光穿梭机来到了19世纪,想再回去已经回不去了,肿么办?
办法其实还是有的,只要上面的命令行窗口还没有被关掉,你就可以顺着往上找啊找啊,找到那个“添加设计文档2”的commit id是1d7505f…,于是就可以指定回到未来的某个版本:
$ git reset --hard 1d7505f
HEAD is now at 1d7505f 添加设计文档2
版本号没必要写全,一般写前7位就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。
再执行git log命令,查看版本库的提交历史:
$ git log --pretty=oneline
1d7505ff878281db3dba47c261e48efc84c0d939 (HEAD -> master) 添加设计文档2
aeb65f4a813ec759c1bd886b196080ec06835414 添加需求文档
2c97086779fc3d4de014689f296d77f8ea4a865f 修改README.txt文件
a235818c40c14a444a0299c1af05e9f774287dce 添加readme文件
果然,我们又回到了最新的那一次提交状态。
Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD从指向你要回退到的那个版本。
现在,你回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的commit id怎么办?
别怕,在Git中,总是有后悔药可以吃的。Git提供了一个命令git reflog用来记录你的每一次命令:
$ git reflog
1d7505f (HEAD -> master) HEAD@{0}: reset: moving to 1d7505f
aeb65f4 HEAD@{1}: reset: moving to HEAD^
1d7505f (HEAD -> master) HEAD@{2}: commit (amend): 添加设计文档2
57c5b17 HEAD@{3}: commit: 添加设计文档
aeb65f4 HEAD@{4}: commit: 添加需求文档
2c97086 HEAD@{5}: checkout: moving from Devlopment to master
93f5bdb (Devlopment) HEAD@{6}: commit: 添加设计文档
2c97086 HEAD@{7}: checkout: moving from master to Devlopment
2c97086 HEAD@{8}: commit: 修改README.txt文件
a235818 HEAD@{9}: commit (initial): 添加readme文件
终于舒了口气,从输出可知,“添加设计文档2”的commit id是1d7505f,现在,你又可以乘坐时光机回到任意版本了。
现在总结一下:
HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id。
穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。
要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。