git底层维护了一个键值对数据库,记录大致分三种,file record,stage-tree,commit-tree,每个file record记录了某个文件在某时刻的完整镜像,这是git控制文件版本的根本。而每个stage-tree记录的是某时刻stage中对应file record的目录结构,每个树节点都是对应file record的引用。commit-tree保存了对应的stage-tree文件及其父commit-tree文件,以此形成commit链。ref文件中对应文件名保存的是对应分支的顶部commit -tree节点。
所以我们每次add文件,本质上就是将每个文件内容插入数据库(因为是键值数据库,所以只有变化的文件才会新生成file record),然后更新stage中的file record,并且生成新的stage-tree条目。而commit,就是将当前最新的stage-tree条目保存进一个新的commit-tree条目,然后设置该commit-tree条目的父条目是当下分支的ref文件对应commit-tree条目,最后将这个新的commit-tree条目设为目前分支的head。