4. Git reset 重置
首先,我们看一下版本库提交历史记录:
image.png
通过 --oneline 可以显示更短小的提交 ID 。
如果我们改变了分支文件中记录的提交 ID ,是不是就可以实现任意提交历史的内容切换呢?是的 ,接下来通过研究 git reset 命令来改变分支引用文件的提交 ID,实现分支内容的重置。
那么,开始操作吧,先看看现在分支中指向的提交 ID 是什么:
image.png
正是我们第二次提交的 ID 。
接下来我们创建一个文件,再进行一次提交,看看 master 分支会不会自动指向最新的提交 ID :
image.png
果然指向了最新的提交 ID 。
master 就像一个游标,可上下浮动,最上方就是指向最新的提交 ID ,向下就可以指向历史提交了,而改变这个游标位置的命令就是 reset 命令。
reset 命令会有一些参数,接下来会细讲。
我们可以通过 reset 回到上一次的提交记录,如下:
image.png
输出表明,确实回到上一次提交了,最新的提交记录和文件都不见了。
其实我们可以通过提交 ID 来重置到任意提交记录,我们重置到初始的提交记录试试:
image.png
重置成功了, welcome.txt 文件内容只有 Hello. 了 。
注意:重置后,历史记录也被丢弃了,通过 git log 命令查询到的历史记录只能从当前的记录到以前的记录,比如现在我们查询到的历史记录只有一条了。
那我们怎么重置到最近的提交记录呢?
答:还有一个挽救机制,通过 .git/logs 目录下的日志文件,该日志文件记录了分支的各种变更。**
我们通过 tail 命令查看一下最后5行的文件内容:
image.png
最新的变更是追加到后面的,这个日志文件很明确地显示了提交 ID 的变动以及变动原因,是 commit 还是 reset 还可能是其他的原因。
通过 git reflog 命令也可以对这个文件进行操作,使用 show 子命令可以显示文件内容:
image.png
与通过 tail 直接查询文件内容不同,最新的改变是显示到最前面的,而且只显示每次操作后的最终的提交 ID ,还有一个容易记忆的 <refname>@{n} 表达式代表指向的提交 ID ,这里的 refname 代表的引用名,这里是 master 。 master@{2} 代表 31ab701
现在,我们回到最新的提交:
image.png
工作区中新增的文件回来了,提交历史也回来了。如果此时我们通过 reflog 查看,就会看到恢复 master 的操作也记录在日志中了:
image.png
reset 命令是常用的命令之一,同时也是最危险最容易误用的命令,常用用法如下:
git reset [ --soft | --mixed | --hard ] [commit]
-
使用参数
--soft,如: git reset --soft [commit] ,会有如下改动:替换引用,指向目标记录ID 。不改变暂存区和工作区。
-
使用参数
--mixed或不使用参数(默认就是--mixed),如:git reset --mixed [commit],会有如下改动:替换引用,指向目标记录ID 。替换暂存区,暂存区的内容和引用指向的目录树内容一致。但不改变工作区。
-
使用参数
--hard,如:git reset --hard [commit],会有如下改动:替换引用,指向目标记录ID 。替换暂存区,暂存区的内容和引用指向的目录树内容一致。并且替换工作区,工作区和暂存区和引用指向的目录树内容一致。
最后,我们再看一下 reset 命令的不同用法:
-
命令:
git reset,相当于git reset HEAD,相当于git reset --mixed HEAD仅用
HEAD指向的目录树重置暂存区、工作区不受影响,相当于之前用git add命令添加到暂存区的内容撤出暂存区。引用的提交ID不变。 -
命令:
git reset -- filename,相当于git reset HEAD --filename仅将文件
filename的改动撤出暂存区,其他文件不变。相当于命令git add filename的反向操作 。 -
命令:
git reset HEAD^,相当于git reset --mixed HEAD^。工作区不改变,但是暂存区会回退到上一次提交之前,引用也会回退到上一次 。
-
命令:
git reset --hard HEAD^工作区、暂存区和引用全都回退到上一次提交的状态,最新的提交内容全部丢掉 。
其他知识:.git/COMMIT_EDITMSG 文件保存了目前最新的提交描述说明,当前提交说明如下:
image.png