浅析Git目录结构以及三大对象

Git目录结构(git bash中执行git init)

 

  • Objects:

存储对象的目录,本地仓库,git中对象分为三种:commit对象,tree对象(多叉树),blob对象;

  • Refs:

存储指向branch的最近一次commit对象的指针,也就是commit对象的sha-1值(就是hash值,sha-1是一种散列算法),refs的目录下包括以下目录(git init后并没有remotes和stash,需要有从remote地址中pull code等交互性操作才会出现remotes目录,stash文件则是做了stash操作才会出现):

 

               heads是存储本地仓库每一个分支最近一次commit对象的sha-1值;

               remotes则是存储最近一次push到远程仓库的commit对象的sha-1值;

              tags(首先要与branch区分开来,tags本质就是branch,与branch不同的是tag是不会有改动的,是历史版本记录)则是存储历史版本的最后一次commit对象的sha-1值

              stash存储藏匿处(就是GitExtentsions中的stash操作)的对象sha-1值;

  • HEAD文件:

该文件表示当前本地签出的分支,例如存储的值:ref: refs/heads/master;

  • Index文件:

存储缓冲区(GitExtensions中的stage)的内容,内容包括它指向的文件的时间戳、文件名、sha1值等;(git三大区域:工作区,缓冲区,历史记录区,如下图)

 

                                                (可对比Git Extensions的操作进行理解)

 

Git对象

git是一套内容寻址系统,它是怎样寻址的呢?Git从核心上来看不过是简单地存储键值对(key-value)(hashmap),大概结构如下:
Key=sha-1(file header + file content)
Value=压缩(file content)

Key是一个40位字符的校验和,前2位作为子目录,后38位作为文件名保存在子目录下。

 

 

       在了解git对象前,先了解学习下git的底层命令。Git分为porcelain命令和plumbing命令,前者是基于后者实现的,porcelain是更高层的命令,举个例子:例如git add, git commit, git push, git pull等命令,而plumbing命令是底层的命令。下面通过plumbing命令进行演示提交。

blob对象 (Plumbing命令演示整个commit过程, 以此理解三大对象)

对象创建:

如何创建一个blob对象呢?
$ echo “version 1” >test.txt
$ git hash-object -w test.txt =》hash-object创建对象,-w表示存储对象,write

$ echo “version 2” >test.txt
$ git hash-object -w test.txt

如何查看创建后的blob对象内容?
$ git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt
=>cat-file命令可将内容取出来,然后放到test.txt文件中,类比linux的cat命令,版本恢复是通过这种方式做到的,根据不同的key进行内容获取,如上面所说内容放在objects目录下;

如何查看对象的类型?
$ git cat-file -t 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
 => -t可以让git返回任何对象类型

对象加入缓冲区:

如何将blob对象加入缓冲区?
git update-index --add --cacheinfo 100644 83baae61804e65cc73a7201a7252750c76066a30 test.txt

update-index会把对象放到缓冲区/暂存区域,即索引库. 该命令表示将test.txt指定的版本加入到缓冲区/暂存区域, key: 83baae61804e65cc73a7201a72 52750c76066a30就是它的版本。注意,这里一定要带上—add选项,因为由于该文件原先并不在暂存区域中 (甚至就连暂存区域也还没被创建出来呢) ,必须传入 --add 参数,而—cacheinfo选项则指出该文件的文件类型,100644表示普通文件.这个时候可以看看Git Extensions的stage区域以及index文件内容。

Git add命令
Git add = git hash-object + git update-index(相当于Git Extensions的add stage操作)

Tree对象

在Git中,所有的内容以tree或者BLOB对象进行存储。可以与linux系统进行类比,tree相当于目录,blob相当于文件内容。一个tree对象可以包含blob对象以及子tree对象。Tree对象是什么时候创建的呢?它的创建介于add和commit命令之间。为什么要创建tree?因为commit对象其实就是指向tree对象的,表明该次commit所对应的tree有哪些内容。

创建tree对象命令:

git write-tree =>它会将缓冲区的内容写成tree对象
把version 1的test.txt加入到缓冲区并且写成tree后,结构如下:

把version 2的test.txt加入到缓冲区:
$ git update-index --add --cacheinfo 100644 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
$ git write-tree

Commit对象

现在有两个tree对象,它们指向了你要跟踪的项目的不同快照,可是先前的问题依然存在:必须记往三个SHA-1 值以获得这些快照。你也没有关于谁、何时以及为何保存了这些快照的信息。commit对象为你保存了这些基本信息。

如何创建commit对象?

git commit-tree key =>需要指定key,例如上面的两个版本,第一个版本和第二个版本的test.txt的key是不一样的;
echo "first commit" | git commit-tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579    
       
如何指定commit对象的parent: 通过-p ?
echo "second commit" | git commit-tree 2f39845a4a2c3ad86adebb00b1ddabd959c131c4 -p 364118

结构图如下:

最后执行git commit -m “test”就可以提交了。

Git官网:

https://git-scm.com/book/zh/v1/Git-%E5%86%85%E9%83%A8%E5%8E%9F%E7%90%86-Git-%E5%AF%B9%E8%B1%A1

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值