$ git checkout develop
Previous HEAD position was 95bf4cf read
$ cat .git/HEAD
ref: refs/heads/develop
如果我们切换分支,那头指针就是指向分支:
$ git checkout 95bf4c
Note: switching to '95bf4c'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
HEAD is now at 95bf4cf read
$ cat .git/HEAD
95bf4cf2e9ba96a406760edbface75b8e4ccf6f9
Git最重要的概念就是工作区,暂存区,版本库。 要弄懂这些就先要看一下git的工作原理是什么,在我们用git init和git clone之后,在本地会生成一个目录,这个就是我们平时开发时候的项目目录,这是一个隐藏目录,这里面就是我们项目信息目录。我之前新建了一个本地仓库,进去看一下.git的目录:
HEAD 文件、 objects 目录、index 文件、refs 目录。 它们都是 Git 的核心组成部分。
.git重要目录详解
HEAD
这里面就是当前头指针的引用,一般是分支引用,然后看到这个指向的refs文件夹中的master分支是一个40位的hash值,就是这个分支上最新提交的commit的hash值。
如果我们切换分支,那头指针就是指向分支:
如果处于分离头指针的状态下,他的值就是某一次的commit。 结论就是HEAD就是指向的分支指针,分支指针指向的就是最新的提交commit。 那HEAD指向的hash值对应的东西是什么呢,来看下一个objects的目录。
objects目录
其实git仓库的所有对象都保存在object文件夹里面,这个就是我们的仓库,我们的文件,图片等都存放在这里,每个文件都是一个二进制文件。
可以看到他是一个40位的hash值,这就是我们的commit对象,以前2位作为文件夹,后38位作为文件名的二进制文件名,在里面包含了4中git类型的对象blob、tree、 commit、tag,一个一个来看一下:
可以通过git cat-file -p hash值来再看一下他里面的内容,这个文件内部,看一下上面的master对应的最新commit。
这就是我们提交的commit对象他里面记录了,他包含了:
然后通过这个tree来看文件夹里面有什么。
前面这个10064代表文件模式:
上面那个commit文件夹中包含了这个tree对象,这个tree对象是一个list,包含了:
继续往下看这个blob对象。
可以看到这个就是我具体文件的内容
这样就可以把上面整个流程给他串起来了: HEAD->master分支->objects中的hash值(commit id)->tree(文件夹)->tree or blob(嵌套文件夹或内容) 这就是你的一个分支包含的内容,所以不管是哪个分支,都是通过这样的流程找到你的代码。
还有一个tag对象,我也新建一个看一下:
tag就和写代码一样的我就在最新的commit上打了一个标签,指向的也是最新的commit对象。
index文件
git的暂存区就在这个index文件中,所以我们也可以把暂存区叫做index。 里面存放了与当前暂存内容相关的信息,包括暂存的文件名、文件内容的SHA1哈希串值和文件访问权限。这也是个二进制文件。具体内容我们看不见。 注:通过这个命令查看不代表我这两个文件在暂存区,他记录了这两个文件的信息。git status就是通过index文件中的内容和工作区以及版本库中的差异来提醒你那些是需要提交的。
refs目录
在上面HEAD的地方,可以看到HEAD就是我们切分支的引用在这个文件夹中,每一个文件都记录着一个hash值,对应的commit。 git就是通过HEAD和refs来判断所在分支和最新的提交。
工作区,暂存区,版本库
看完.git目录后,再来理解这三个重要的区域。
工作区
就是开发代码的目录,除去.git目录,剩下的就是工作区。
暂存区
暂存区其实就是这个.git/index文件。里面记录着目录和文件的引用hash值,而不是真正的文件对象。
版本库
版本库其实就是.git/objects目录
再来走一遍流程: 当我们git add的时候,其实是做了2件事:
所以暂存区实际上就是一个包含文件索引的目录树,他记录了文件名、文件的状态信息(时间戳、文件长度等),实际文件在存在 Git 对象库(.git/objects)中。
然后git commit的时候,其实做了下面3件事:
参考资料
Git 内部原理 Git原理及使用