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的介绍。
说是数据对象比较抽象,其实就是二机制文件,包含三种类型的内容。
- 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和refs/head/master是等效的,另外master是refs/head/master的v简写也是等效的。看下HEAD文件的内容。
文章图片
refs/head/master文件的内容是一个commit类型的hash.
文章图片
在log中查看下这个hash。原来HEAD、master和refs/head/master都存储着我们最近一次提交的commID。
文章图片
上帝视觉
我们离线操作无非是工作区、暂存区、本地库,暂存区对应的文件的hash就存在index中;本读库对应的内容的hash存在objects中hasn类型为tree和commit类型的文件中;objetcs中的hash类型为blob的文件则存储了我们所有文件,包括在暂存区和已经commit的。
推荐阅读
- Git|开源协议与git分支
- Git|Git入门,什么是git,如何使用git以及git分支概念
- eng|Github - 第一篇(Github安装与配置)
- eng|Github - 第三篇(分支操作案例)
- 理解git暂存区
- 源代码管理SVN|源代码管理工具SVN和Git小结
- git使用|git---主分支同步到子分支
- CSCI 2134 Using Git
- Git合并策略选项及示例