git本地仓库和暂存区

git是可以离线操作的,包括"git add"、"git commit"等很多命令都能离线执行,所以这些命令涉及的数据肯定都是有本地存储的,比如commit的id、message、author,历史修改的文件等,那么这些数据是存储在哪里的?答案是.git文件。
git本地仓库和暂存区
文章图片

上图展示了.git下的所有文件,下面对index,objects,HEAD,refs这些文件夹分析。
.git/index
通过"git add"命令可以把更新的文件加入到暂存区,可以认为index是暂存区的存储文件,index包括了加入到暂存区的文件以及未更新的文件,这些文件通过hash指向和文件路径代表。

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

    虽然看到hash确实改变了,但是这个hash是如何映射文件内容的呢,看下面objects的介绍。
.git/objects
说是数据对象比较抽象,其实就是二机制文件,包含三种类型的内容。
  1. commit类型的,其hash值的前两位定义为文件夹名称,后38位定义为文件名称,内容是commit的message、author、parent、tree等信息。
    a. 执行"git log --pretty=raw"可以看最近的提交日志。
    git本地仓库和暂存区
    文章图片

    b. 这些信息就是记录在objects文件夹下的,我们试着找commitID为“e4a4482cf8163dadf861161803ea06460c5940b5”对应的文件。
    git本地仓库和暂存区
    文章图片

    c. 通过"git cat-file -t "查看hash类型。
    git本地仓库和暂存区
    文章图片

    d. 通过"git cat-file -p"查看文件内容,正是 git log打印的。
    git本地仓库和暂存区
    文章图片
  2. blob类型的,也就是文件路径和文件名,hass值在objects中也是前两位对应文件夹后38位对应文件名称。
    a. 执行“git ls-files -p”查看index文件内容。
    git本地仓库和暂存区
    文章图片

    b. 查看hash类型。
    git本地仓库和暂存区
    文章图片

    c. 在objects中的位置。
    git本地仓库和暂存区
    文章图片

    d. 查看下文件内容,正是加入到暂存区中的内容。
    git本地仓库和暂存区
    文章图片
  3. tree类型的,也就是每次提交都会通过一个tree包含本次提交涉及的所有文件。
    a. 同样通过"git log --pretty=raw"找一个tree类型的hash。
    git本地仓库和暂存区
    文章图片

    b. 查看hash类型。
    git本地仓库和暂存区
    文章图片

    c. 查看objects中的位置。
    git本地仓库和暂存区
    文章图片

    d. 同样的查看文件内容,可以看到包括了本次更新和未更新的所有文件的blob hash。
    git本地仓库和暂存区
    文章图片
.git/HEAD,.git/ref/head/master
【git本地仓库和暂存区】这俩放在一块是因为在使用时 HEAD和refs/head/master是等效的,另外master是refs/head/master的v简写也是等效的。看下HEAD文件的内容。
git本地仓库和暂存区
文章图片

refs/head/master文件的内容是一个commit类型的hash.
git本地仓库和暂存区
文章图片

在log中查看下这个hash。原来HEAD、master和refs/head/master都存储着我们最近一次提交的commID。
git本地仓库和暂存区
文章图片

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

    推荐阅读