【总结】
1、git log 查看提交历史的commit id
2、git reset --hard commit_id
注意:如果出现Unlink of file '.......' failed.Should I try again?(y/n),说明有其他程序在操作git目录下的文件,比如应用程序、dos命令窗或者git bash,导致git无法关联此文件,要关闭掉所有使用该文件的应用程序,重新git reset即可。
===================================================
开始这节学习之前,我们尝试对readme.txt文件再次进行如下修改:
<span style="font-size:14px;">Git is a distributed version control system.
Git is free software under GPL.</span>
我们将其再次提交到仓库,还是两步哦(add 和 commit):
大现在为止,请回忆一下我们一共对readme.txt修改并提交了几次呢?如果你按照本教程从头开始认真学习的话,你肯定能回答出“我们一共修改并提交了3次”。不错,你回答正确。但是大家想一样,如果是多人合作修改readme.txt,你还能凭回忆答出readme.txt一共修改并提交了几次吗?肯定不能吧。因为你的记性再好也只能记住自己对readme.txt的修改和提交,而不能知道他人对readme.txt文件修改和提交次数。
【git log查看commit历史】
那么,我们如何知道仓库中的一个文件,到目前版本为止一共修改了提交了几次呢?git给我们提供了一个命令。那就是:
<span style="font-size:14px;">git log</span>
在我们的仓库中,执行上面的命令,输入结果是:
从上面的结果我们可以看到,readme.txt一共有3次commit,并且列出了每次commit的作者、日期,以及每次commit时填写的描述信息。git log命令的输出结果是由近及远的,最上面的commit是最近一次commit,最下面的commit是最早一次commit。
从git log输出结果中,我们还看到了每次commit都有一大串数字,那串数字是一个哈希码,用来唯一标示1次commit。
git log是显示所有的commit,Page Up、Page Down、↓、↑来控制显示
退出log显示则按q+回车即可
如果只想显示最近的N次提交则使用git log -n N
【退回到历史版本】
在git中,当前版本是用HEAD版本来标识的,前一个版本使用HEAD^来表示,上上个版本使用HEAD^^来表示。那么前100个版本如何表示呢?我们不可能写100个^,我们有简便写法,那就是HEAD^100。用这种简便写法,上上个版本可以这样表示HEAD^2。
我们知道,我们当前是在“append GPL”这个版本上。那么,如果我想回退到上一个版本,也就是“add distributed to readme file”上,该怎么办?可以使用git reset命令:
从这个命令,可以看到当前版本(HEAD标识)已经在“add distributed to readme file”版本上了,如果不放心,可以看看当前readme.txt文件的内容:
发现确实是“add distributed to readme file”版本。
那么如果我想继续退回到“wrote a readme file”上呢? 是git log --hard HEAD^2吗?在执行回退命令之前,我们一定要用git log查看下当前版本库的提交状态。我们执行git log,输出如下:
从上面的输出发现,当前的版本是“add distributed to readme file”版本(最上面的commit),“wrote a readme file”版本只是它的上一个版本 ,所以不能用git log --hard HEAD^2命令,而是应该用git log --hard HEAD^命令。我们执行下git log --hard HEAD^命令,看下输出:
发现HEAD目前位于“wrote a readme file”版本上了。所以,我们已经把版本退回到了“wrote a readme file”版本上了。
我们也可用哈希码代替上面的HEAD^等。
通过上面的经验,我们推荐大家在执行回退之前,一定要先用git log查看当前版本库的提交状态,在执行回退命令。
【穿越回来】
如果你对退回到历史版本后悔了,想回到历史版本以后的某个版本,怎么办?需要两步:
第一步:使用git reflog查看HEAD变动的历史。
因为任何一个commit都曾是HEAD的位置。所以找到HEAD的历史,就能找到任何一个commit。
上面的输出结果也是从上到下由近及远排列的。可以看到HEAD变动的历史。我们对HEAD的变动进行一下说明。我们从最底下开始往上说:
第一次变动是:commti “wrote a readme file”,HEAD指向0f8d88c;
第二次变动是:commit “add distributed to readme file”,HEAD指向d926915;
第三次变动是:commit “append GPL”,HEAD指向35c1ae8;
第四次变动是:reset操作,将HEAD移动到d926915,也就是“add distributed to readme file”版本
第五次变动是:reset操作,将HEAD移动到0f8d88c,也就是“append GPL”版本。
由此,可以看到每一个版本的哈希码的前6位,因为一个哈希码对应一个版本。
第二步:git reset --hard commit_id
穿越回来
随意可以通过git reset --hard commit_id
来穿越到任何版本。例如我们想回到最新版本,则执行命令:
可以看到,当前HEAD位于35c1ae8版本上, 也就是“append GPL”版本上。
【git reflog 与 git log区别】
git reflog 可以查看所有分支的所有操作记录(包括commit和reset的操作),包括已经被删除的commit记录,git log则不能察看已经删除了的commit记录
具体一个例子,假设有三个commit, git st:
commit3: add test3.c
commit2: add test2.c
commit1: add test1.c
如果执行git reset --hard HEAD~1则 删除了commit3,如果发现删除错误了,需要恢复commit3,这个时候就要使用git reflog
HEAD@{0}: HEAD~1: updating HEAD
63ee781 HEAD@{1}: commit: test3:q
红色加粗的即是被删除了的 commit3,运行git log则没有这一行记录
可以使用git reset --hard 63ee781将红色记录删除,则恢复了cmmit3,运行git log后可以看到:
commit3: add test3.c
commit2: add test2.c
commit1: add test1.c