这一篇的内容比较难以理解。容易搞混。你要有心理准备。我会尽量解释的清楚一点。
我们已经知道了工作区,暂存区和版本库了。我们还说了,Git管理的是修改,而不是文件。所以你要知道的一点是:事实上不是”文件“在这三个地方跑来跑去,而是一个叫”修改“的家伙在这三个地方跑来跑去——此处的”修改”你可以理解成一个名词。
当你在工作区对某一个文件进行修改时(这里的修改是动词),就有一个“修改”(名词)诞生在工作区了。当你git add的时候,这个“修改”(名词)就跑到了暂存区,准备提交。当你git commit的时候,这个“修改”(名词)就跑到了版本库,被Git所记录,当成了一个快照。
还没混吧?
很好,接下来来点狠得,看你能不能承受得住。
我们还得清楚一件事:“修改”(名词)只能从工作区产生。然后跑到暂存区,再跑到版本库。
这是一个正常的故事顺序,中间没有波折。这样的故事平淡如水,没什么意思。现在我们就给这个故事加一点波折。比如说你在工作区产生了一个“修改”(名词),现在你又不想要这个“修改”(名词),希望恢复。这时有几种情况需要分析一下:
- 第1种情况是,你在工作区产生的这个“修改”还没有git add添加到暂存区。你当然可以直接打开编辑器改回到之前的样子,但我们希望Git来帮我们做这件事。此时,就有一个命令可以帮助你:git checkout -- file。比如你在readme.md中新添加了一行文本“this is a test.”。
Git is amazing!
I love Git!
this is a test.
这时候就产生了一个“修改”(名词),现在你后悔了,觉得不应该添加这一行。可以使用git checkout -- file:
$ git checkout -- readme.md
输入完命令以后没有任何提示。没有提示就是最好的提示,证明你没错。
这时你再打开readme.md查看一下,发现刚才添加的“this is a test.”这一行已经没有了。工作区的状态跟版本库里的一样。你可以想象成,git checkout -- file这个命令把刚才产生在工作区的“修改”(名词)给杀掉了。
无图无真相
工作区的“修改”被杀了
- 第2种情况是,你先是在工作区产生了一个“修改”,然后git add 添加到了暂存区,接着你又在工作区产生了一个“修改”。很简单嘛!git checkout -- file 搞定!但是,事情不再是你想象的那样哦。比如,你先在readme.md中新加了一行“this is a new line.”
Git is amazing!
I love Git!
this is a new line.
这时候会在工作区产生一个“修改”,然后你git add,把这个“修改”添加到了暂存区:
$ git add readme.md
这时候你又在工作区进行了修改,添加了新的一行“this is an anthor new line.”
Git is amazing!
I love Git!
this is a new line.
this is an anthor new line.
然后你checkout:
$ git checkout -- readme.md
这时候你再打开readme.md,会发现:
Git is amazing!
I love Git!
this is a new line.
你发现“this is an anthor new line.”这个“修改“被杀掉了,但是“this is a new line.”这个“修改”仍然还在,而且你再checkout一下仍然没用。“修改”一旦跑到暂存区,checkout就杀不了他了。
不过,你放心,我们仍然有办法。
git checkout -- file命令中的 -- (两个短横)很重要,没有这两个短横,就变成了切换分支命令了。后面还会再说。
如果一个“修改”进入到了暂存区,而你想把这个“修改”给杀掉,这是做不到了,你只能把这个“修改”打回到工作区,然后在工作区把这个“修改”给杀掉。
那怎么把暂存区的“修改”打回到工作区呢?
很简单,一个命令:git reset HEAD file
$ git reset HEAD file
Unstaged changes after reset:
M readme.md
这个时候,“修改”就被打回到了工作区,此时,你打开readme.md查看,发现仍然是:
Git is amazing!
I love Git!
this is a new line.
这是当然的了,因为“修改”只是被打回到了工作区,但他还没死。在工作区,杀死一个“修改”就很简单了,直接git checkout -- file搞定!
将暂存区的“修改”回退到工作区
好学的你可能又要问了:那如果“修改”被提交到了版本库那该怎么办呢?
那就更简单了,还记得前面《历史记录(第5篇)》中说的吗?从当前版本回退到前一个版本该怎么做?你要知道的是,一旦“修改”被提交到了版本库,他就得道成仙了,你只能回退到原来的版本,不能动不动就杀掉他了。
那回退到原来的版本怎么做呢?还记得吗?
答对了!
$ git reset --hard HEAD^
你可能发现版本回退的命令和把“修改”从暂存区打回到工作区的命令很相似。是的,reset本来就是重置的意思。区别在于二者的选项和参数不同。要注意区分哦。
好了,这一节啰嗦了这么多,希望对你有帮助。
听完这一讲,你应该对“Git管理的是修改而不是文件”这句话有了更深的理解了吧。
如果喜欢的话,可以关注我的微博http://weibo.com/qiaoer2017
网友评论