第7章 Git重置
上一章讲解了版本库中对象的存储方式,以及分支master的实现。即master分支在版本库的引用目录(.git/refs)中体现为一个引用文件.git/refs/heads/master,其内容就是分支中最新提交的提交ID。
$cat.git/refs/heads/master
e695606fc5e31b2ff9038a48a3d363f4c21a3d86
上一章还通过对提交本身数据结构的分析看到,提交可以通过对父提交的关联实现对提交历史的追溯。注意,下面的git log命令中使用了—oneline参数,类似于—pretty=oneline,但是可以显示更短小的提交ID。参数—oneline在Git 1.6.3及以后的版本中才有,老版本的Git可以使用参数—pretty=oneline—abbrev-commit替代。
$git log—graph—oneline
*e695606 which version checked in?
*a0c641e who does commit?
*9e8a761 initialized.
那么,是不是有新的提交发生的时候,master分支对应的引用文件中的内容就会改变呢?master分支对应的引用文件中的内容可以人为地改变吗?本章就来探讨如何用git reset命令改变分支引用文件的内容,即实现分支的重置。
7.1 分支游标master探秘
先来看看当有新的提交发生的时候,文件.git/refs/heads/master的内容如何改变。首先在工作区创建一个新文件,姑且叫作new-commit.txt,然后提交到版本库中。
$touch new-commit.txt
$git add new-commit.txt
$git commit-m "does master follow this new commit?"
[master 4902dc3]does master follow this new commit?
0 files changed,0 insertions(+),0 deletions(-)
create mode 100644 new-commit.txt
此时工作目录下会有两个文件,其中文件new-commit.txt是新增的。
$ls
new-commit.txt welcome.txt
来看看master分支指向的提交ID是否改变了。
可以看出在版本库引用空间(.git/refs/目录)下的master文件内容的确改变了,指向了新的提交。
$cat.git/refs/heads/master
4902dc375672fbf52a226e0354100b75d4fe31e3
再用git log查看一下提交日志,可以看到刚刚完成的提交。
$git log—graph—oneline
*4902dc3 does master follow this new commit?
*e695606 which version checked in?
*a0c641e who does commit?
*9e8a761 initialized.
引用refs/heads/master就好像是一个游标,在有新的提交发生的时候指向了新的提交。可是如果只可上、不可下,就不能称为“游标”。Git提供了git reset命令,可以将“游标”指向任意一个存在的提交ID。下面的示例就尝试人为地更改游标。(注意下面的命令中使用了—hard参数,会破坏工作区未提交的改动,慎用。)
$git reset—hard HEAD^
HEAD is now at e695606 which version checked in?
还记得上一章介绍的HEAD^代表了HEAD的父提交吗?这条命令就相当于将master重置到上一个老的提交上。我们来看一下master文件的内容是否更改了。
$cat.git/refs/heads/master
e695606fc5e31b2ff9038a48a3d363f4c21a3d86
果然,master分支的引用文件的指向更改为前一次提交的ID了,而且通过下面的命令可以看出新添加的文件new-commit.txt也丢失了。
$ls
welcome.txt
重置命令不仅可以重置到前一次提交,而且还可以直接使用提交ID重置到任何一次提交。
(1)通过git log查询到最早的提交ID。
$git log—graph—oneline
*e695606 which version checked in?
*a0c641e who does commit?
*9e8a761 initialized.
(2)然后重置到最早的一次提交。
$git reset—hard 9e8a761
HEAD is now at 9e8a761 initialized.
(3)重置后会发现welcome.txt也回退到原始版本库,曾经的修改都丢失了。
$cat welcome.txt
Hello.
使用重置命令很危险,会彻底地丢弃历史。那么,还能够通过浏览提交历史的办法找到丢弃的提交ID,再使用重置命令恢复历史吗?不可能!因为重置让提交历史也改变了,提交日志如下:
$git log
commit 9e8a761ff9dd343a1380032884f488a2422c495a
Author:Jiang Xin<jiangxin@ossxp.com>
Date:Sun Nov 28 12:48:26 2010+0800
initialized.