git是能够离线操作的,包含"git add"、"git commit"等很多命令都能离线执行,所以这些命令波及的数据必定都是有本地存储的,比方commit的id、message、author,历史批改的文件等,那么这些数据是存储在哪里的?答案是.git文件。

上图展现了.git下的所有文件,上面对index,objects,HEAD,refs这些文件夹剖析。

.git/index

通过"git add"命令能够把更新的文件退出到暂存区,能够认为index是暂存区的存储文件,index包含了退出到暂存区的文件以及未更新的文件,这些文件通过hash指向和文件门路代表。

  1. 在工作区对add-me文件进行了批改。(M代表了批改,第二列的M代表是未退出暂存区的)
  2. 通过“git ls-files -s”查看此时index文件(二进制的)的内容。第二列是blob类型的hash,blob我了解就是门路类型的,第四列是文件门路和名称。
  3. 通过git add add-me把文件存入暂存区。(M色彩变了并且跑到第一列代表在暂存区然而未退出本地库)
  4. 此时的index文件内容,看add-me对应的文件曾经更新了。

    尽管看到hash的确扭转了,然而这个hash是如何映射文件内容的呢,看上面objects的介绍。

.git/objects

说是数据对象比拟形象,其实就是二机制文件,蕴含三种类型的内容。

  1. 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打印的。
  2. blob类型的,也就是文件门路和文件名,hass值在objects中也是前两位对应文件夹后38位对应文件名称。
    a. 执行“git ls-files -p”查看index文件内容。

    b. 查看hash类型。

    c. 在objects中的地位。

    d. 查看下文件内容,正是退出到暂存区中的内容。
  3. 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。

上帝视觉

咱们离线操作无非是工作区、暂存区、本地库,暂存区对应的文件的hash就存在index中;本读库对应的内容的hash存在objects中hasn类型为tree和commit类型的文件中;objetcs中的hash类型为blob的文件则存储了咱们所有文件,包含在暂存区和曾经commit的。