Git还是从底层命令开始吧

Git 是一套内容寻址文件系统,那么Git是怎么进行寻址呢?其实,寻址无非就是查找,而Git采用HashTable的方式进行查找,也就是说,Git只是通过简单的存储键值对(key-value pair)的方式来实现内容寻址的,而key就是文件(头+内容)的哈希值(采用sha-1的方式,40位),value就是经过压缩后的文件内容。因此,在接下来的实践中,会经常通过40位的hash值来进行底层命令操作,几乎每一个底层命令都需要通过key来指定所要操作的对象。

一.Git的三种对象类型

1.BLOB(binary large object)对象:BLOB对象可以存储几乎所有的文件类型

2.tree对象:用来组织BLOB对象的一种数据类型

3.commit对象:每一次的提交操作,由tree对象衍生,每一个commit对象表示一次提交,在创建的过程中可以指定该commit对象的父节点,这样所有的commit操作便可以连接在一起,而这些commit对象便组成了提交树,branch只不过是这个树中的某一个子树罢了。

二.Git对象存储方式为:key-value

key=sha1(file_header + file_content)

value=zlib(file_content)

Git 将文件头与原始数据内容拼接起来,并计算拼接后的新内容的 40位的sha-1校验和,将该校验和的前2位作为object目录中的子目录的名称,后38位作为子目录中的文件名;然后,Git 用zlib的方式对数据内容进行压缩,最后将用 zlib 压缩后的内容写入磁盘.

三.对象暂存(缓存)区---------->了解git add的背后.Git如何使用底层命令完成文件索引操作的!

git add命令在底层命令中被分为两步:

1.通过git hash-object命令将需要暂存的文件进行key-value化转换成Git对象,并进行存储,拿到这些文件的key

git hash-object #获取指定文件的key,如果带上-w选项,则会将该对象的value进行存储

2.通过git  update-index命令将这些对象加入到暂存区进行暂存,这样便完成了Git文件的暂存操作

git update-index #将指定的object加入索引库,需要带 --add选项

查看key对应的文件信息:

git cat-file –p  -t key #获取指定key的对象信息,-p打印详细信息,-t打印对象的类型

四.实验验证-------->使用底层命令实现git add的操作

1)mkdir test  && cd test && git init 

2)该目录下会生成.git目录,查看.git/objects 目录下面没有文件 --------->find .git/objects -type f

Git 初始化了 objects 目录,同时在该目录下自动创建 pack 和 info 子目录,但是该目录下没有其他常规文件

3)将文件转换成git对象:

将该文件转换为Git的对象并存储

解释:

A) 参数w 指示hash-object命令存储数据,若不指定这个参数该命令仅仅返回键值

B)该命令输出长度为 40 个字符的校验和

C)objects 目录下会生成一个文件,这便是 Git 存储数据内容的方式

hash-objec命令会返回该Git对象的key值,这时到.git目录的objects目录下会发现,多一个19的目录,该目录下有一个0a18037c64c43e6b11489df4bf0b9eb6d2c9bf的文件

4).查看存储文件的内容和git对象的类型:

查看存储文件的内容和git对象的类型

5)将git对象加入到暂存库中:

放入暂存区

--cacheinfo  指定文件类型: 100644代表普通文件

此时.git目录下会多一个index文件,以后每次每次update-index命令执行之后,该index文件的内容都会发生变化.

以上git add操作的底层命令已经完成.


五.index文件简谈

index是一个索引文件,存放的是暂存区的整个目录树的信息,并且为目录树中的每个文件都保存了时间戳和长度

1.index文件的格式为: 

Index魔数(DIRC) + 版本号 + 暂存的文件个数 + 每个文件的时间戳和长度

2. Index索引库记录从项目初始化到目前为止,项目仓库中所有文件最后一次修改时刻的时间戳以及对应的长度信息,因此随着加入仓库中的文件不断增多,index文件也会不断增大.

3.git status命令,则会把每一个文件的索引信息和上次提交的索引信息进行比较,如果发生了变化,就会显示出来.

4.暂存操作会对每一个文件计算校验和(即前面提到的 SHA-1 哈希字串),然后把当前版本的文件快照保存到 Git 仓库中(Git 使用 blob 类型的对象存储这些快照),并将校验和加入暂存区域.

六.创建树节点

1.在Git中,所有的内容以tree或者BLOB对象进行存储.,其中 tree 对象对应于 UNIX 中的目录blob 对象则大致对应于 inodes 或文件内容.

一个单独的tree对象包含一条或多条tree记录,每一条记录含有一个指向BLOB对象或子tree对象的sha-1指针(也就是一个40位的key值),并附有该对象的权限模式 、类型和文件名信息.

创建tree对象只是add和commit中间的一个缓冲步骤,因为commit对象要根据tree对象来创建

2.创建tree对象:

创建tree对象

解释: cat-file -t显示该对象的类型是tree,表明tree对象创建成功.至此,tree节点创建完成.

由于index暂存区包括了项目仓库中所有的文件,因此commit对象所对应的tree对象,永远都是工作目录的根tree对象。也就是说,每次commit,都是把工作目录的根目录所对应的tree对象,链接给此次的commit对象;而且,在Git中,每个子目录都对应一个tree对象,每个文件对应一个BLOB对象,因此整个工作目录对应一棵Git对象树,根节点就是commit对象所引用的tree节点,而每个子文件夹又分别对应一棵子树。所以任何一个文件的更改,都会导致其上层所有父对象的更改和重新存储

七.commit对象

在Git中,每一次commit都对应一个commit对象,而一个commit对象对应一个tree对象,该tree对象是工作目录的根tree对象.

1.创建commit对象

创建tree对象

解释: 

1)由于这是第一次提交,因此不需要带上-p选项来指明父节点

2)该commit对象中包含了与之关联的tree对象的key值,以及author和committer的信息

3)git log --stat key命令,该命令会打印指定commit对象之前的所有提交记录

2.目前为止blob对象,tree对象,commit对象之间的关系:

第一次提交后Git对象关系图

八.提交树---->commit tree

操作要求:在第一次提交的基础上完成第二次提交和第三次提交,

第二次提交会提交ceshi的第二个版本和增加一个新的文件并提交;

第三次提交会演示在tree对象中构造子tree对象并提交.

在下面的每一次提交中,还需要指定每一次提交的前继提交对象,这样commit对象便连接在一起,形成一棵提交树.

第二次提交操作:

1.修改ceshi文件和创建newfile文件并将文件转变成git对象:

转换成git对象

此时.git/object目录下会存在a5和1e目录.

2.将git对象添加早暂存区中:

放入暂存区中

3.利用暂存区创建tree对象

创建tree对象

4.根据该tree对象创建commit对象

指定前继tree对象

5.查看commit对象的内容:

查看commit对象的内容

6.目前位置git对象关系:

 第二次提交后Git对象关系图

第三次提交(演示在tree对象中构造子tree对象并提交):

1.将版本1中的tree对象读取到暂存区中:

git read-tree --prefix=bak 39314df08ba40c2cd50eb0276fc80129189efaa2

解释:在读取的过程中,需要加--prefix选项,否则无法成功读取,这是因为在index中相同路径的文件只能出现一次,由于ceshi已经存在于index索引库了,因此如果想把第一个版本的tree对象读取进来,需要将该版本的ceshi放在文件夹bak中

2.创建tree对象并提交commit对象:

创建tree对象并提交commit对象

3.查看tree对象包含的内容:

.查看tree对象包含的内容

4.git对象之间的关系:

第三次提交后Git对象关系图
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • Add & Commit git init 初始化一个 Git 仓库(repository),即把当前所在目录变成...
    冬絮阅读 4,674评论 0 8
  • git 使用笔记 git原理: 文件(blob)对象,树(tree)对象,提交(commit)对象 tree对象 ...
    神刀阅读 3,714评论 0 10
  • 一、 Git 常用命令速查 git branch 查看本地所有分支 git status 查看当前状态 git c...
    走在路上的日子阅读 1,882评论 0 22
  • 一、 Git 常用命令速查 git branch 查看本地所有分支 git status 查看当前状态 git c...
    不变秃也能变强阅读 980评论 0 9
  • 以下笔记主要参考gitgot,大致了解git使用和原理。 第一部分我们从个人的视角去研究如何用好Git,并且揭示G...
    carolwhite阅读 2,288评论 0 1