Git三棵树和reset/checkout命令

理解Git没有比从三棵树开始更好的了。

完整的话还是看git文档比较好,说的蛮清楚了。

三棵树和正向流程

用途
HEAD 上一次提交的快照,下一次提交的父结点
Index 预期的下一次提交的快照
Working Directory 沙盒

git的核心工作就是管理这三棵树。git add就是把你工作目录(Working Directory)的修改提交到暂存区(Index),git commit就是把暂存区的内容同步到仓库里作为一个快照,并移动HEAD指向新快照;

git_flow

额外说一下这个HEAD指针,每一次commit都相当于在仓库(Repository)里生成一个快照, 把N个快照想象成一个右进左出的队列(List),再想象有一个指针,默认指向队首(最新快照),告诉你当前到底用的是哪一个版本快照。

reset

显然,git reset就是对上述行为的反向操作。

reset的本质其实是移动HEAD指针指向哪个快照,而通过

  • --soft——只改变指针指向的快照;
  • --mixed——移动指针的同时也把快照内容同步到暂存区;
  • --hard——三棵树全同步为指针指向的快照;

参数来递进的控制改变是发生在哪几颗树上。

git_reflow

再强调一遍,reset的改变的是HEAD指针,而不是文件。即使git reset File的写法是有效的,但它的本质是git reset --mixed HEAD File的缩写,即将FileHEAD指向的快照复制到索引中。HEAD指针永远只能指向一个快照,但是快照是可以局部修改它里面的文件的。

HEAD~表示前一个快照,HEAD~2表示前两个,依此类推。

checkout

checkout的本质就有所不同,它关心的是分支(branch),它的主要作用是让HEAD在不同分支间移动(默认三棵树都会更新)。

还是拿刚才那个队列举例,分支相当于是平行的一条队列,现在把他放在你脑子里之前那个队列的上方, 由于HEAD指针只能指向一个快照,所以这个时候它可能会在两个队列间“跳动”,checkout就是控制指针上下移动的命令,而reset则是控制指针在当前队列左右(前后)移动。

git_chechout

同样的,checkout后面也可以跟一个文件,和git reset --hard [branch] file可能会产生的效果一样。

Lex Wayne
Lex Wayne
Python Knight & Go Padawan

You see, madness, as you know, is like gravity.

相关