最近在学git操作,特此记录一下
上图源自GIT官网,由此可以看见,每个新版本中都有全部文件的快照。那么问题就来了,**快照到底以什么方式存在?**以及在全部文件中,有修改和未修改的区分,对于未修改的文件,当前版本该文件的快照是否沿用上一个版本的快照呢?
对于修改的文件是否产生了新的快照呢,新旧快照又怎么查看区分呢?
好,带着上面问题进行本文阅读:
在操作之前需要先介绍一下
每次commit会产生一个commit对象,以及一个tree对象和多个blob对象[此对象数量取决于文件数量]
tree对象用于记录当前目录结构和文件索引,blob对象则是文件的真实快照。
git add 暂存命令会为每个文件进行校验和计算,这些校验和正是git对文件快照的索引,add命令后,这些校验和会被添加到暂存区,等待commit操作生成tree对象,这些索引被存放在tree对象里面,见上图
所有的对象都可以在.git/objects目录下面进行查找
实践
首先创建一个本地仓库,并添加readme.txt文件,添加’hello world’内容到文件中,如下
见上图,当前.git/obejcts目录下只有info,pack文件夹,在commit操作之后,该目录下会多出几个目录加下图
通过git log可以发现,本次commit对象的id为64cae5b
通过git cat-file -p
一层层查看,最终确定了readme.txt文件快照,这就回答了第一个问题
添加新的文件demo.txt,并提交,并查看本次提交的tree对象
第二次提交的tree中对文件readme.txt的索引保持不变,这就回答了第二个问题,即每次提交对未修改的文件会保持其索引不变
修改readme.txt文件内容后,再次查看文件快照索引
此时readme.txt文件的快照索引发生了改变,所以git是通过索引来进行区分
【结论】每次commit操作会产生一个与之对应的tree对象,其中记录了本次commit,所有文件的索引,即快照,只有本次commit修改的文件才会产生新的快照文件,未修改的文件快照会沿用上次的快照索引,所以每次commit操作不会保存所有文件一次,而是对修改过的文件进行一次保存,至于git为啥可以在本次commit中所有所有文件,功劳归功于tree对象