本文以一个具体例子结合动图介绍了Git的内部原理,包括Git是怎么储存我们的代码和变更历史的、更改一个文件时,Git内部是怎么变化的、Git这样实现的有什么好处等等 。
通过例子解释清楚上面这张动图,让大家了解Git的内部原理 。如果你已经能够看懂这张图了,下面的内容可能对你来说会比较基础 。
文章插图
前言近几年技术发展十分迅猛,让部分同学养成了一种学习知识停留在表面,只会调用一些指令的习惯 。我们时常有一种“我会用这个技术、这个框架”的错觉,等到真正遇到问题,才发现事情没有那么简单 。
而Git也是一个大部分人都知道如何去使用它,知道有哪些命令,却只有少部分人知道具体原理的东西 。了解一些底层的东西,可以更好的帮你理清思路,知道你真正在操作什么,不会迷失在Git大量的指令和参数上面 。
Git是怎么储存信息的这里会用一个简单的例子让大家直观感受一下git是怎么储存信息的 。
首先我们先创建两个文件
$ git init$ echo '111' > a.txt$ echo '222' > b.txt$ git add *.txt
Git会将整个数据库储存在.git/目录下,如果你此时去查看.git/objects目录,你会发现仓库里面多了两个object 。$ tree .git/objects.git/objects├── 58│└── c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c├── c2│└── 00906efd24ec5e783bee7f23b5d7c941b0c12c├── info└── pack
好奇的我们来看一下里面存的是什么东西$ cat .git/objects/58/c9bdf9d017fcd178dc8c073cbfcbb7ff240d6cxKOR0a044K%
怎么是一串乱码?这是因为Git将信息压缩成二进制文件 。但是不用担心,因为Git也提供了一个能够帮助你探索它的api git cat-file [-t] [-p],-t可以查看object的类型,-p可以查看object储存的具体内容 。$ git cat-file -t 58c9blob$ git cat-file -p 58c9111
可以发现这个object是一个blob类型的节点,它的内容是111,也就是说这个object储存着a.txt文件的内容 。这里我们遇到第一种Git object,blob类型,它只储存的是一个文件的内容,不包括文件名等其他信息 。然后将这些信息经过SHA1哈希算法得到对应的哈希值58c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c,作为这个object在Git仓库中的唯一身份证 。
也就是说,我们此时的Git仓库是这样子的:
文章插图
我们继续探索,我们创建一个commit 。
$ git commit -am '[+] init'$ tree .git/objects.git/objects├── 0c│└── 96bfc59d0f02317d002ebbf8318f46c7e47ab2├── 4c│└── aaa1a9ae0b274fba9e3675f9ef071616e5b209...
我们会发现当我们commit完成之后,Git仓库里面多出来两个object 。同样使用cat-file命令,我们看看它们分别是什么类型以及具体的内容是什么 。$ git cat-file -t 4caaa1tree$ git cat-file -p 4caaa1100644 blob 58c9bdf9d017fcd178dc8c0...a.txt100644 blob c200906efd24ec5e783bee7...b.txt
这里我们遇到了第二种Git object类型——tree,它将当前的目录结构打了一个快照 。从它储存的内容来看可以发现它储存了一个目录结构(类似于文件夹),以及每一个文件(或者子文件夹)的权限、类型、对应的身份证(SHA1值)、以及文件名 。此时的Git仓库是这样的:
文章插图
$ git cat-file -t 0c96bfcommit$ git cat-file -p 0c96bftree 4caaa1a9ae0b274fba9e3675f9ef071616e5b209author lzane 李泽帆1573302343 +0800committer lzane 李泽帆1573302343 +0800[+] init
接着我们发现了第三种Git object类型——commit,它储存的是一个提交的信息,包括对应目录结构的快照tree的哈希值,上一个提交的哈希值(这里由于是第一个提交,所以没有父节点 。在一个merge提交中还会出现多个父节点),提交的作者以及提交的具体时间,最后是该提交的信息 。此时我们去看Git仓库是这样的:
文章插图
到这里我们就知道Git是怎么储存一个提交的信息的了,那有同学就会问,我们平常接触的分支信息储存在哪里呢?
$ cat .git/HEADref: refs/heads/master$ cat .git/refs/heads/master0c96bfc59d0f02317d002ebbf8318f46c7e47ab2
在Git仓库里面,HEAD、分支、普通的Tag可以简单的理解成是一个指针,指向对应commit的SHA1值 。
推荐阅读
- DDos之SYN Flood攻击原理与使用金盾防火墙进行防护 AI云
- Github上这5款非常好用的开源 Docker 工具,京东、华为都在用
- 咖啡|咖啡一杯1.5被狂薅羊毛!瑞幸回应:内部运营人员配置失误
- 贡茶内部奶茶制作配方,港式奶茶制作配方是什么
- 整理下公司内部MySQL使用规范,分享给大家
- 黑客全家桶、文字提取利器、深度学习 500 问 | GitHub 热点速览
- 喝这茶饮可降血压
- 程序员最大社交网站github图片显示异常的解决方法
- 深度分析:mybatis的底层实现原理,看完你学会了吗?
- 只用个低危SSRF提权就能进内网