Git对象

上一节了解了 Git 的一个重要的概念:暂存区。

暂存区是一个介于工作区和版本库的中间状态,当执行commit时,实际上是将暂存区的内容提交大版本库中,而执行add则是将本次变更添加到暂存区。

上一节中也出现了很多新的问题?比如说 HEAD 是什么?它与 master 是什么关系?

 

Git对象库探秘

  前面我们查看提交日志的时候,出现了提交ID,一个由40位十六进制数字组成的SHA1哈希值,通过查看日志的详细输出,会看看到更多的SHA1哈希值。

  

  可以看出,一个提交当中包含了三个用 SHA1哈希值 标识的Git 对象ID

  1,commit  99447928556fbc66f267bdcdcd8b4a84678cda60  这是本次提交的唯一标识;

  2,tree     2f468676a412dd91435ad6b8c3706eebba13fa9c  这是本次提交所对应的目录树;

  3,parent   1f2cc329be37c7678bac8c2d1f696effffe61c08     这是本次提交的父提交(上一次提交,第一个提交是没有parent的)

  

  可以使用 git cat-file 命令来彻底研究Git 对象ID,分别查看一下上面的三个对象ID的类型

  

  注意:在引用对象ID的时候,没有必要把整个40位的ID写全,只要保证从头开始的前几位不冲突就行,一般在日常工作中输入前6位即可。

  

  再使用 git cat-file 命令来查看一下对象内容

  

  查看目录树(tree对象)中看到了一个新类型的对象:blob 对象(二进制大对象),这个 blob 对象就保存着 index.html 文件的内容。我们继续使用 git cat-file 命令来查看该 blob对象。

  

  

 

  那么这些对象都存放在什么地方呢?当然是Git版本库中(.git目录)的 objects 目录下了,对象ID的前2位作为目录,后38位最为文件名

  

  

  下面的图片展示了Git对象库中各个对象之间的关系

  

  通过 Commit 对象之间的相互关联,可以很容易地识别出一条跟踪链条,这条跟踪链条可以在运行 git log 命令时候通过 --graph选项查看。--pretty=raw参数用于显示每个提交对象的parent属性

  

  最后一个提交没有parent属性,所以跟踪链到此为止,这实际上就是提交的起点。

  

  

  

  OK,我们再来看看 HEADmaster

  命令 git branch 是分支管理的主要命令,也可以显示当前所在分支

  

  在 master 分支名称前面的星号(*)表明这个分支是当前工作分支,至于什么是分支,后面会有一节专门介绍分支。

  现在连续执行下面的三个命令会看到相同的输出:

  1,git log HEAD

  2,git log master

  3,git log refs/heads/master

  

  这个结果说明了什么呢?

  结果表明,在当前的Git版本库中,HEADmasterrefs/heads/master 具有相同的指向!!!现在就到Git版本库(.git目录)中看看究竟。

  首先,在 .git 目录下找到名字为 HEAD 或者 master 的文件,并查看一下 .git/HEAD 文件的内容:

  

  

  .git/HEAD文件的内容翻译过来就是:”指向一个引用:refs/heads/master“。这个就是文件 .git/refs/heads/master了,ok,再看一下.git/refs/heads/master文件的内容:

  

  又是一个SHA1哈希值,那么用 git cat-file 命令来查看它:

  

  这个内容是不是很面熟!原来 master 分支指向的是一个最新的提交ID

  这就是Git分支的实现原理:从任何一个提交开始建立一条历史跟踪链条,用一个文件指向这个链条的最新提交,该文件就可以追踪整个提交历史了,这个文件就是 .git/refs/heads/master

  下面的图标显示了一个完整的真实的版本库结构:

  

  目录 .git/refs 是保存引用的命名空间,其中 .git/refs/heads 目录下的引用又称为分支。

  对于分支,即可以使用正规的长格式的表示打:refs/heads/master ,也可以去掉前面的两级目录用 master 来表明。

原文地址:https://www.cnblogs.com/startcaft/p/6632971.html