GIT中数据的存储与组织

2019-08-29  本文已影响0人  躺在家里干活

GIT中数据的存储与组织

我们经常使用一些Git的命令,例如checkoutcommit等命令,这些都是高级命令,有一些比较底层的命令,对我们查看数据很有帮助

命令 说明
git hash-object 存储数据对象
find .git/objects -type f 查看objects目录下的文件
git cat-file -p [hashcode] 显示存储的内容

GIT的数据目录

### 初始化Git仓库
$ git init

$ cd .git

$ ll
total 24
-rw-r--r--   1 sparrow  staff    23B 12 24 16:01 HEAD
drwxr-xr-x   2 sparrow  staff    64B 12 24 16:01 branches
-rw-r--r--   1 sparrow  staff   137B 12 24 16:01 config
-rw-r--r--   1 sparrow  staff    73B 12 24 16:01 description
drwxr-xr-x  13 sparrow  staff   416B 12 24 16:01 hooks
drwxr-xr-x   3 sparrow  staff    96B 12 24 16:01 info
drwxr-xr-x   4 sparrow  staff   128B 12 24 16:01 objects
drwxr-xr-x   4 sparrow  staff   128B 12 24 16:01 refs

重要的目录列表:

目录名 目录作用
HEAD 指向目前被检出的分支
index 文件保存暂存区的信息
objects 存储所有数据内容
refs 目录存储指向数据(分支)的提交对象的指针

GIT数据的存储

如何存储文件

# sparrow @ localhost in ~/Documents/learning/test on git:master o [16:07:34] C:1
$ find .git/objects -type f

# sparrow @ localhost in ~/Documents/learning/test on git:master o [16:07:47]
$ echo '测试内容' | git hash-object -w --stdin
a936e260776b0c97788d90fb9e87e133c6401364

# sparrow @ localhost in ~/Documents/learning/test on git:master o [16:09:16]
$ find .git/objects -type f
.git/objects/a9/36e260776b0c97788d90fb9e87e133c6401364

# sparrow @ localhost in ~/Documents/learning/test on git:master o [16:09:21]
$ git cat-file -p a936e260776b0c97788d90fb9e87e133c6401364
测试内容

我们可以看到数据的存储方式:一个文件对应一条内容,以该内容加上特定头部信息一起的 SHA-1 校验和为文件命名。校验和的前两个字符用于命名子目录,余下的 38 个字符则用作文件名。

如何存储变更的文件

# sparrow @ localhost in ~/Documents/learning/test on git:master o [17:26:43]
$ echo '1111' > 1.txt

# sparrow @ localhost in ~/Documents/learning/test on git:master x [17:29:38]
$ git hash-object -w 1.txt
5f2f16bfff90e6620509c0cf442e7a3586dad8fb

# sparrow @ localhost in ~/Documents/learning/test on git:master x [17:29:45]
$ find .git/objects -type f
.git/objects/5f/2f16bfff90e6620509c0cf442e7a3586dad8fb
.git/objects/a9/36e260776b0c97788d90fb9e87e133c6401364

# sparrow @ localhost in ~/Documents/learning/test on git:master x [17:30:21]
$ echo '2222' > 1.txt

# sparrow @ localhost in ~/Documents/learning/test on git:master x [17:31:14]
$ git hash-object -w 1.txt
c7dc989f8044a4fcf16361414998e14694e1ac7e

# sparrow @ localhost in ~/Documents/learning/test on git:master x [17:31:23]
$ find .git/objects -type f
.git/objects/5f/2f16bfff90e6620509c0cf442e7a3586dad8fb
.git/objects/c7/dc989f8044a4fcf16361414998e14694e1ac7e
.git/objects/a9/36e260776b0c97788d90fb9e87e133c6401364

上面的命令,是存储了一个txt文件,之后修改这个文件,再次存储,可以看到文件变更后又存储了一个新的文件。但是有个明显的问题就是,我们始终没有看到存储的文件名称

GIT的文件种类

文件类型 描述 存储的信息
commit 提交组建 每次提交之后产生,会把所有文件信息创建一个tree文件,以及提交信息,用户信息
tree 文件树 存储这个tree下有哪些文件,有文件类型,文件hash值,文件名称
blob 文件 文件的具体内容(会被压缩)

GIT:Commit && Tree

### 新增一个1.txt文件,并且提交:


$ git commit -m'第一次提交'
[master (root-commit) f2e5a15] 第一次提交
 1 file changed, 1 insertion(+)
 create mode 100644 1.txt

$ git cat-file -p master^{tree}
100644 blob c7dc989f8044a4fcf16361414998e14694e1ac7e    1.txt

$ find .git/objects -type f
.git/objects/66/58043fa729b52ab982f5fd48aa35a3992dbca0
.git/objects/f2/e5a15e35c55cd773496dd6092953a2deeaaf29
.git/objects/c7/dc989f8044a4fcf16361414998e14694e1ac7e

$ git cat-file -p 66580
100644 blob c7dc989f8044a4fcf16361414998e14694e1ac7e    1.txt

$ git cat-file -t f2e5a
commit

$ git cat-file -p f2e5a
tree 6658043fa729b52ab982f5fd48aa35a3992dbca0
author sparrow <chwangyanan@foxmail.com> 1545645214 +0800
committer sparrow <chwangyanan@foxmail.com> 1545645214 +0800

第一次提交

从上面可以看出,如果我们进行了新的提交,就会出现一个新的commit文件,然后这个文件中包含一个tree文件的 hash值,而这个tree文件的内容则包含文件名,当然也可以是tree的名称(相当于目录的概念)

提交记录Commit

### 新增一个文件 */dir1/2.txt*

$ find .git/objects -type f
.git/objects/66/58043fa729b52ab982f5fd48aa35a3992dbca0
.git/objects/e5/cbfdee257934ed2cf026ce17ca868f3a4b1705
.git/objects/c7/dc989f8044a4fcf16361414998e14694e1ac7e
.git/objects/ee/4cc7e06ea6b72d9d92534e37cc0ee5fe8622cf
.git/objects/f2/e5a15e35c55cd773496dd6092953a2deeaaf29
.git/objects/e4/8f67e7f3128750710269e1baccadd83ac151ad
.git/objects/8a/666e85a8ec9b8d4a2bad19c976892ac1bc948d

$ git cat-file -p e5cbf
tree ee4cc7e06ea6b72d9d92534e37cc0ee5fe8622cf
parent f2e5a15e35c55cd773496dd6092953a2deeaaf29
author sparrow <chwangyanan@foxmail.com> 1545645896 +0800
committer sparrow <chwangyanan@foxmail.com> 1545645896 +0800

带目录的提交

$ git cat-file -p e48f6
dir1->111

$ git cat-file -p 8a666
100644 blob e48f67e7f3128750710269e1baccadd83ac151ad    2.txt

$ git cat-file -p ee4cc
100644 blob c7dc989f8044a4fcf16361414998e14694e1ac7e    1.txt
040000 tree 8a666e85a8ec9b8d4a2bad19c976892ac1bc948d    dir1

可以发现:

  1. 目录被储存为一个tree文件。
  2. 提交记录里面多了parent一行,指向前一次提交的hash。
  3. 1.txt的记录会被再次存储

HEAD指向

$ cat .git/HEAD
ref: refs/heads/master

看下HEAD,发现指向ref中的文件

$ cat .git/refs/heads/master
e5cbfdee257934ed2cf026ce17ca868f3a4b1705

会发现有一个hash值,这个值就是第二次提交后生成的commit文件的hash值。

分支的信息

### 新建dev分支

$ git branch dev

$ git branch
* master
dev

### 进入.git/refs/heads目录,查看分支信息
$ cd .git/refs/heads

$ ll
total 16
-rw-r--r--  1 sparrow  staff    41B 12 24 18:28 dev
-rw-r--r--  1 sparrow  staff    41B 12 24 18:04 master

$ cat dev
e5cbfdee257934ed2cf026ce17ca868f3a4b1705

$ cat master
e5cbfdee257934ed2cf026ce17ca868f3a4b1705

可以看到,dev 和 master 指向同一个CommitHEAD指向这里的master

### 通过拷贝文件的方式创建一个新的分支
$ cp dev dev2

$ git branch
* master
dev
dev2
### 这个时候可以去看下,HEAD文件已经指向dev2

我的个人博客,有空来坐坐

上一篇 下一篇

猜你喜欢

热点阅读