git是可以离线操作的,包括"git add"、"git commit"等很多命令都能离线执行,所以这些命令涉及的数据肯定都是有本地存储的,比如commit的id、message、author,历史修改的文件等,那么这些数据是存储在哪里的?答案是.git文件。
上图展示了.git下的所有文件,下面对index,objects,HEAD,refs这些文件夹分析。
.git/index
通过"git add"命令可以把更新的文件加入到暂存区,可以认为index是暂存区的存储文件,index包括了加入到暂存区的文件以及未更新的文件,这些文件通过hash指向和文件路径代表。
- 在工作区对add-me文件进行了修改。(M代表了修改,第二列的M代表是未加入暂存区的)
- 通过“git ls-files -s”查看此时index文件(二进制的)的内容。第二列是blob类型的hash,blob我理解就是路径类型的,第四列是文件路径和名称。
- 通过git add add-me把文件存入暂存区。(M颜色变了并且跑到第一列代表在暂存区但是未加入本地库)
- 此时的index文件内容,看add-me对应的文件已经更新了。
虽然看到hash确实改变了,但是这个hash是如何映射文件内容的呢,看下面objects的介绍。
.git/objects
说是数据对象比较抽象,其实就是二机制文件,包含三种类型的内容。
- commit类型的,其hash值的前两位定义为文件夹名称,后38位定义为文件名称,内容是commit的message、author、parent、tree等信息。
a. 执行"git log --pretty=raw"可以看最近的提交日志。
b. 这些信息就是记录在objects文件夹下的,我们试着找commitID为“e4a4482cf8163dadf861161803ea06460c5940b5”对应的文件。
c. 通过"git cat-file -t "查看hash类型。
d. 通过"git cat-file -p"查看文件内容,正是 git log打印的。
- blob类型的,也就是文件路径和文件名,hass值在objects中也是前两位对应文件夹后38位对应文件名称。
a. 执行“git ls-files -p”查看index文件内容。
b. 查看hash类型。
c. 在objects中的位置。
d. 查看下文件内容,正是加入到暂存区中的内容。
- tree类型的,也就是每次提交都会通过一个tree包含本次提交涉及的所有文件。
a. 同样通过"git log --pretty=raw"找一个tree类型的hash。
b. 查看hash类型。
c. 查看objects中的位置。
d. 同样的查看文件内容,可以看到包括了本次更新和未更新的所有文件的blob hash。
.git/HEAD,.git/ref/head/master
这俩放在一块是因为在使用时 HEAD和refs/head/master是等效的,另外master是refs/head/master的v简写也是等效的。看下HEAD文件的内容。
refs/head/master文件的内容是一个commit类型的hash.
在log中查看下这个hash。原来HEAD、master和refs/head/master都存储着我们最近一次提交的commID。
.git/logs
所有的操作都会记录下来,而logs中的HEAD就负责存储这些数据。通过git reflogs也可以查看所有操作的数据。
上帝视觉
我们离线操作无非是工作区、暂存区、本地库,暂存区对应的文件的hash就存在index中;本读库对应的内容的hash存在objects中hasn类型为tree和commit类型的文件中;objetcs中的hash类型为blob的文件则存储了我们所有文件,包括在暂存区和已经commit的。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。