git详解(二)理解git对象

本文详细解析git commit对象,HEAD和master的关系,以及40位hash数字的生成原理。通过学习,理解git对象结构、HEAD的引用机制和SHA1算法在git中的应用。
摘要由CSDN通过智能技术生成

git详解(二)理解git对象

摘要: 本章是在初步了解git stage基础上继续的延伸,介绍什么是HEAD,master,这两个究竟是啥东西,有啥关系,为啥我们git log看到的commit log都是40位的16进制数字,这些数字是怎么生成的?为啥要这样表示?可不可以按数值递增来表示?通过这一篇的学习,我们会解决这些疑惑
关键字: git 对象,git commit,HEAD, master

1.git commit对象

我们在git工作目录下看一下提交历史

git log --pretty=raw
fox@fox:~/Documents/demo$ git log --pretty=raw
commit d4c1f0765b0b58ce464d95989f2ebfe4094f4f54
tree fb090206bb44349ff5fc52d85fb94107f1d0ce92
parent ba7f561a2798f2b41a7131888bdbc58531ba89c5
author fox <leehaoran111@163.com> 1478439077 +0800
committer fox <leehaoran111@163.com> 1478439077 +0800

    ok

commit ba7f561a2798f2b41a7131888bdbc58531ba89c5
tree a41e7c2f7c9bed661a30b996a4cb7468898c227c
parent 0e94145e01eb5da2420dd8a47d103aeab1dff44b
author fox <leehaoran111@163.com> 1478435045 +0800
committer fox <leehaoran111@163.com> 1478435045 +0800

    commit

commit 0e94145e01eb5da2420dd8a47d103aeab1dff44b
tree c3b8bb102afeca86037d5b5dd89ceeb0090eae9d
author fox <leehaoran111@163.com> 1476806519 +0800
committer fox <leehaoran111@163.com> 1476806519 +0800

    add test.txt

可以看到,一个提交里面有commit id,tree id,parent id,这分别表示啥呢?
这里我们介绍一个新的命令git cat-file,这个命令可以查看版本库对象的内容和类型信息,在分析git对象的时候十分有用,详情可以git help cat-file看一下(这儿也可以看出,最好的git教程就是git help,强烈建议遇到不懂的命令时先git help ,至少可以提高我们的学习能力,stay hungry,stay fool,开始时git help的越多,发现自己懂得越少,当我们git help发现很多都是熟悉的时候,对git应该算很熟悉了,当然离参与改进git还有段距离,我现在是属于第一阶段,因此一块学习,一块进步)
我们使用以下git cat-file

fox@fox:~/Documents/demo$ git cat-file -t d4c1f07
commit
fox@fox:~/Documents/demo$ git cat-file -p d4c1f07
tree fb090206bb44349ff5fc52d85fb94107f1d0ce92
parent ba7f561a2798f2b41a7131888bdbc58531ba89c5
author fox <leehaoran111@163.com> 1478439077 +0800
committer fox <leehaoran111@163.com> 1478439077 +0800

ok
fox@fox:~/Documents/demo$ git cat-file -t fb090206
tree
fox@fox:~/Documents/demo$ git cat-file -p fb090206
040000 tree 151ae54e1d0d34303df4d59ace2c023d0ef5278a    hran
100644 blob 7aeee4f72cc77cc564fcc3aa7fd03caea3542fcb    test.txt
fox@fox:~/Documents/demo$ git cat-file -t ba7f561a
commit
fox@fox:~/Documents/demo$ git cat-file -p ba7f561a
tree a41e7c2f7c9bed661a30b996a4cb7468898c227c
parent 0e94145e01eb5da2420dd8a47d103aeab1dff44b
author fox <leehaoran111@163.com> 1478435045 +0800
committer fox <leehaoran111@163.com> 1478435045 +0800

commit
fox@fox:~/Documents/demo$ git cat-file -p 7aeee4f
hello world
git diff demo
amend some to test
fox@fox:~/Documents/demo$ ^C
fox@fox:~/Documents/demo$ git cat-file -p 151ae54
100644 blob be932f84e9104853c0dcf2088c60442320fff6ce    test.c
fox@fox:~/Documents/demo$ git cat-file -p be932f84

s

可以看出,每次的提交都是一个commit对象,然后这个commit对象里面存放着一个tree对象和一个parent对象,另外还有提交信息,一个parent对象也是一个commit对象,一个tree对象包含blob对象或tree对象,blob对象里面存放的就是对应文件的内容,那这些对象保存到哪里了?当然是在.git/objects下面了hash值前位是目录,后38位是文件,当然这文件是不能直接打开的,更是不可以修改的,因为每一个hash值与文件内容都有关系,一旦修改了,就相当于破坏了对象库。

fox@fox:~/Documents/demo/.git/objects/7a$ ll
total 12
drwxrwxr-x  2 fox fox 4096 116 20:23 ./
drwxrwxr-x 15 fox fox 4096 116 21:31 ../
-r--r--r--  1 fox fox   60 116 20:23 eee4f72cc77cc564fcc3aa7fd03caea3542fcb

从上面的分析可以看出git对象结构如下
这里写图片描述

2 HEAD 与master

我们看下HEAD和master的commit id

fox@fox:~/Documents/demo$ git rev-parse HEAD
d4c1f0765b0b58ce464d95989f2ebfe4094f4f54
fox@fox:~/Documents/demo$ git rev-parse master
d4c1f0765b0b58ce464d95989f2ebfe4094f4f54
fox@fox:~/Documents/demo$ git log -1
commit d4c1f0765b0b58ce464d95989f2ebfe4094f4f54

发现它们都一样,看下它们存在了.git的哪里

fox@fox:~/Documents/demo$ find .git -name HEAD -o -name master
.git/logs/HEAD
.git/logs/refs/heads/master
.git/HEAD
.git/refs/heads/master

我们先看下.git/HEAD

fox@fox:~/Documents/demo$ cat .git/HEAD
ref: refs/heads/master
fox@fox:~/Documents/demo$ cat .git/refs/heads/master 
d4c1f0765b0b58ce464d95989f2ebfe4094f4f54

这里可以看出HEAD是指向refs/heads/master的一个引用,而后者里面就是一个commit id
可以看出git 版本库结构应该如下图所示:
版本库结构图
至于refs目录会在后面涉及到分支的时候详细介绍

3 40位的hash数字怎么来的

sha1(secure hash algorithm)是一个加密算法,可以保证根据2^64位以内的消息算出160bit的数字序列,也就是40个16进制的数字,这样有一个好处,就是人们不能根据随后生成的数字计算出消息内容,也不能让不同内容的文本计算出同样的hash数字,保证了数字序列的唯一性。
看下HEAD对应的commit信息

fox@fox:~/Documents/demo$ git cat-file commit HEAD
tree fb090206bb44349ff5fc52d85fb94107f1d0ce92
parent ba7f561a2798f2b41a7131888bdbc58531ba89c5
author fox <leehaoran111@163.com> 1478439077 +0800
committer fox <leehaoran111@163.com> 1478439077 +0800

ok
fox@fox:~/Documents/demo$ git cat-file commit HEAD |wc -c
203
fox@fox:~/Documents/demo$ (printf "commit 203\000";git cat-file commit HEAD)|sha1sum
d4c1f0765b0b58ce464d95989f2ebfe4094f4f54  -
对比一下HEAD的commit id
fox@fox:~/Documents/demo$ git rev-parse HEAD
d4c1f0765b0b58ce464d95989f2ebfe4094f4f54

是不是可以看出40位数字是怎么来的了呢?对象类型+字符数\000+内容
我们接下来验证一下:

fox@fox:~/Documents/demo$ git cat-file blob HEAD:test.txt
hello world
git diff demo
amend some to test
fox@fox:~/Documents/demo$ git cat-file blob HEAD:test.txt | wc -c
45
fox@fox:~/Documents/demo$ (printf "blob 45\000";git cat-file blob HEAD:test.txt)|sha1sum
7aeee4f72cc77cc564fcc3aa7fd03caea3542fcb  -
fox@fox:~/Documents/demo$ git rev-parse HEAD:test.txt
7aeee4f72cc77cc564fcc3aa7fd03caea3542fcb

是不是一样的呢?现在我们就知道了git里面的40位数字是怎么来的了

总结

本文延续上一文,介绍了git对象,HEAD, master的区别,还有git 里面的40位sha1码的来源。通过 这一文的学习,对git对象的理解又加深了不少,接下来会介绍git 的一些其它操作。
注:如果感觉到文章里面有些困惑,不用怀疑,一定是我讲的不好

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值