文章插图
【Git内部原理揭秘】其实还有第四种Git object,类型是tag,在添加含附注的tag(git tag -a)的时候会新建,这里不详细介绍,有兴趣的朋友按照上文中的方法可以深入探究 。
至此我们知道了Git是怎么储存一个文件的内容、目录结构、commit信息和分支的 。其本质上是一个key-value的数据库加上默克尔树形成的有向无环图(DAG) 。这里可以蹭一下区块链的热度,区块链的数据结构也使用了默克尔树 。
Git的三个分区接下来我们来看一下Git的三个分区(工作目录、Index 索引区域、Git仓库),以及Git变更记录是怎么形成的 。了解这三个分区和Git链的内部原理之后可以对Git的众多指令有一个“可视化”的理解,不会再经常搞混 。
接着上面的例子,目前的仓库状态如下:
文章插图
这里有三个区域,他们所储存的信息分别是:
- 工作目录 ( working directory ):操作系统上的文件,所有代码开发编辑都在这上面完成 。
- 索引( index or staging area ):可以理解为一个暂存区域,这里面的代码会在下一次commit被提交到Git仓库 。
- Git仓库( git repository ):由Git object记录着每一次提交的快照,以及链式结构记录的提交变更历史 。
文章插图
运行echo "333" > a.txt将a.txt的内容从111修改成333,此时如上图可以看到,此时索引区域和git仓库没有任何变化 。
文章插图
运行git add a.txt将a.txt加入到索引区域,此时如上图所示,git在仓库里面新建了一个blob object,储存了新的文件内容 。并且更新了索引将a.txt指向了新建的blob object 。
文章插图
运行git commit -m 'update'提交这次修改 。如上图所示
- Git首先根据当前的索引生产一个tree object,充当新提交的一个快照 。
- 创建一个新的commit object,将这次commit的信息储存起来,并且parent指向上一个commit,组成一条链记录变更历史 。
- 将master分支的指针移到新的commit结点 。
如果不能很好的将日常使用的指令“可视化”出来,推荐阅读 图解Git
一些有趣的问题有兴趣的同学可以继续阅读,这部分不是文章的主要内容
问题1:为什么要把文件的权限和文件名储存在tree object里面而不是blob object呢?想象一下修改一个文件的命名 。
如果将文件名保存在blob里面,那么Git只能多复制一份原始内容形成一个新的blob object 。而Git的实现方法只需要创建一个新的tree object将对应的文件名更改成新的即可,原本的blob object可以复用,节约了空间 。
问题2:每次commit,Git储存的是全新的文件快照还是储存文件的变更部分?由上面的例子我们可以看到,Git储存的是全新的文件快照,而不是文件的变更记录 。也就是说,就算你只是在文件中添加一行,Git也会新建一个全新的blob object 。那这样子是不是很浪费空间呢?
这其实是Git在空间和时间上的一个取舍,思考一下你要checkout一个commit,或对比两个commit之间的差异 。如果Git储存的是问卷的变更部分,那么为了拿到一个commit的内容,Git都只能从第一个commit开始,然后一直计算变更,直到目标commit,这会花费很长时间 。而相反,Git采用的储存全新文件快照的方法能使这个操作变得很快,直接从快照里面拿取内容就行了 。
当然,在涉及网络传输或者Git仓库真的体积很大的时候,Git会有垃圾回收机制gc,不仅会清除无用的object,还会把已有的相似object打包压缩 。
问题3:Git怎么保证历史记录不可篡改?通过SHA1哈希算法和哈系树来保证 。假设你偷偷修改了历史变更记录上一个文件的内容,那么这个问卷的blob object的SHA1哈希值就变了,与之相关的tree object的SHA1也需要改变,commit的SHA1也要变,这个commit之后的所有commit SHA1值也要跟着改变 。又由于Git是分布式系统,即所有人都有一份完整历史的Git仓库,所以所有人都能很轻松的发现存在问题 。
推荐阅读
- DDos之SYN Flood攻击原理与使用金盾防火墙进行防护 AI云
- Github上这5款非常好用的开源 Docker 工具,京东、华为都在用
- 咖啡|咖啡一杯1.5被狂薅羊毛!瑞幸回应:内部运营人员配置失误
- 贡茶内部奶茶制作配方,港式奶茶制作配方是什么
- 整理下公司内部MySQL使用规范,分享给大家
- 黑客全家桶、文字提取利器、深度学习 500 问 | GitHub 热点速览
- 喝这茶饮可降血压
- 程序员最大社交网站github图片显示异常的解决方法
- 深度分析:mybatis的底层实现原理,看完你学会了吗?
- 只用个低危SSRF提权就能进内网