【Git】git的三个区域与文件的三种状态以及.git目录解析

git三个区域与文件的三种状态

git的三个区域

1、Git 的工作目录

2、暂存区域

3、以及本地仓库

文件的三种状态

对于任何一个文件,在 Git 内都只有三种状态:

1、已修改(modified) --> Git 的工作目录

2、已暂存(staged) -->暂存区域

3、已提交(committed) -->本地仓库

已修改表示修改了某个文件,但还没有提交保存;

已暂存表示把已修改的文件放在下次提交时要保存的清单中。

已提交表示该文件已经被安全地保存在本地数据库中了;

由此我们看到 Git 管理项目时,文件流转的三个工作区域:Git 的工作目录,暂存区域,以及本地仓库。
在这里插入图片描述
在这里插入图片描述

.git文件夹目录结构

在这里插入图片描述
1 、hooks文件夹:

这个目录存放一些shell脚本,可以设置特定的git命令后触发相应的脚本;

在搭建gitweb系统或其他git托管系统会经常用到hook script。

2、info文件夹:

包含git仓库的一些信息

3 、logs文件夹:

保存所有更改的引用记录,继续打开logs文件夹,有refs文件夹和HEAD文件

请看下图中
(1)HEAD文件
主要记录每次的变更操作,所有类型的变更都会记录的哦,

git reflog命令查询出的列表就是HEAD中存储的列表
在这里插入图片描述
(2)继续打开refs文件夹,可以看到heads文件夹、remotes文件夹和stash文件

I : stash文件存储的是所有你使用git stash命令暂存的记录,是一个列表。使用git stash list时,查询出的列表就是从stash中取出来的。

II:heads文件里面存储的是一系列的本地分支的对象,每个对象的文件名就是本地的一个分支名,使用git branch查看本地分支命令时,查询出的所有本地分支就是取的heads文件夹下所有文件的名称。

III:remotes文件夹里存储的是远端的一系列分支的对象,每个对象的文件名称就是远端的一个分支名称,使用git branch -a查看远端分支命令时,查询出的所有本地分支就是取的remotes文件夹下所有文件的名称。
在这里插入图片描述
4、objects文件夹

该目录存放所有的Git对象,对象的SHA1哈希值(一共40位)的前两位是文件夹名称,后38位作为存在相应文件夹下对象的文件名。

比如0b这个文件夹,它里面有一系列git对象(也就是文件),里面所有文件的38位的名称加上0b,就组成原来的40位的哈希值了。

更近一步说,我们每次提交新文件到git上时,这时会根据该文件内容计算生成一个40位的哈希值,假如生成的是0c7bcc3f8f1c5311d06e3067f7f7dddecb8668fe,这个文件的存储方式就是先截取0c作为文件夹名称,然后后面的38位7bcc3f8f1c5311d06e3067f7f7dddecb8668fe作为文件名称,存储在0c文件夹下。

如果这时你又提交了一个文件或者修改了一个文件碰巧又生成一个以0c开通的哈希值,那么这个时候就会直接截取该哈希值的后38位作为该次生成的git对象的文件名,存储在原来已经存在的0c文件夹下。

在这里插入图片描述
在这里插入图片描述

5、refs文件夹
在这里插入图片描述
(1)heads文件夹
该文件夹存储的是所有的本地分支文件,每一个本地分支文件中,存储的是一个哈希值,每一次commit都是生成一个对应的哈希值,然后用这次新生成的哈希值,替换掉原来这个分支文件中的哈希值。

如下三张图,红色的代表新提交的三个文件,然后
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(2)stash文件
该文件夹是使用git stash命令时,会将生成的git对象的哈希值存储到stash文件里,更进一步说stash文件中,就存了一个40位的哈希值。对应的git对象在objects文件夹里。使用git stash pop时,会先去stash文件中,找到该哈希值(或者也可以认为是指针),然后到对应的objects文件夹下,查找对应的git对象,将其中的数据取出来,转换成我们能看懂的代码

I、继续打开tags文件夹

当使用git tag v1.0给当前分支,打上标签时,就会在tags文件夹下,生成对应文件,文件里存储的是当前分支所对应的哈希值,以后就可以使用v1.0这个标签来代替分支名称,通常发布稳定的线上版本时,使用这种做法。方便以后查询,因为使用标签容易记,更简洁。
在这里插入图片描述

6、COMMIT_EDITMSG文件提交的是最近一次提交的描述信息

7、 config:这个是GIt仓库的配置文件

8、 description:仓库的描述信息,主要给gitweb等git托管系统使用

9、 index:这个文件就是我们前面提到的暂存区(stage),是一个二进制文件

10、HEAD文件里面只存储了当前分支的关联

补充

commit 的真相

每一次你创建一个文件并跟踪它会发现,git 会对其进行压缩然后以 git 自己的数据结构形式来存储。这个压缩的对象会有一个唯一的名字,即一个哈希值,这个值存放在 object 目录下。

在探索 object 目录前,我们先要问自己 commit 到底是何方神圣。commit 大致可以视为你工作目录的快照,但是它又不仅仅只是一种快照。

实际上,当你提交的时候,为创建你工作目录的快照 git 只做了两件事:

  1. 如果这个文件没有改变,git 仅仅只把压缩文件的名字(就是哈希值)放入快照。
  2. 如果文件发生了变化,git 会压缩它,然后把压缩后的文件存入 object 目录。最后再把压缩文件的名字(哈希值)放入快照。
    这里只是简单介绍,整个过程有一点复杂,以后的博客里会作说明的。

一旦快照创建好,其本身也会被压缩并且以一个哈希值命名。那么所有的压缩对象都放在哪里呢?答案是object 目录。
在这里插入图片描述
这就是我创建一个空文件 file_1.txt 并提交后 object 目录看起来的样子。请注意如果你的文件的哈希值是“89faaee…”,git 会把这个文件存在 “89” 目录下然后命名这个文件为 “faaee…”。

你会看到3个哈希。一个对应 file_1.txt ,另一个对应在提交时所创建的快照。那么第三个是什么呢?其实是因为 commit 本身也是一个对象并且也被压缩存放在 object 目录下。

现在,你需要记住的是一个 commit 包含四个部分:

  1. 工作目录快照的哈希
  2. 提交的说明信息
  3. 提交者的信息
  4. 父提交的哈希值
  5. 如果我们解压缩一个提交,你自己可以看看到底是什么:

在这里插入图片描述
这是我看到的
在这里插入图片描述
如你所见我们得到了所期望看到的的:快照的哈希,作者,提交信息。这里有两样东西很重要:

  1. 正如预料的一样,快照的哈希 “86550…” 也是一个对象并且能在object目录下找到。
  2. 因为这是我的第一个提交,所以没有父提交。

那我的快照里面到底是些什么呢?
在这里插入图片描述
到这里我们看到的最后一个对象是我们先前提到的唯一会存在于快照中的对象。它是一个 blob(二进制文件),这里就不作深究了。


分支,标签,HEAD 都是一家人
那么现在你知道 git 的每一个对象都有一个正确的哈希值。现在我们来看看 HEAD 吧!那么,在 HEAD 里又有什么呢?

在这里插入图片描述
这看起来 HEAD 不是一个hash,倒是容易理解,因为 HEAD 可以看作一个你目前所在分支的指针。如果我们看看 refs/heads/master,就会发现这些:
在这里插入图片描述
是不是很熟悉?是的,这和我们第一个提交的哈希完全一样。由此表明分支和标签就是一个提交的指针。明白这一点你就可以删除所有你想删除的分支和标签,而他们指向的提交依然在那里。只是有点难以被访问到。如果你想对这部分了解更多,请参考git book。

猜你喜欢

转载自blog.csdn.net/qq_42322103/article/details/95001008