#git底层设计
git是Linus的分布式版本控制软件,据说用了一周写出来,太强了。
##目标
版本控制的目标是,记录每次更改,或者说记录每个版本。除此之外还有额外要求:
- 低成本创建分支
- 保证版本内容的可信性,不被篡改
- 分布式
##思路
我第一个想到的实现方式是,增量存储,记录变更的内容。换句话说,存储的是一堆diff文件。这样的好处是,理论上存储空间会小。但是每一个版本的内容都会是从某一个版本为基础根据diff计算而来。
然而,信息的存储方式其实只是技术细节,关键的问题在于,如何把部分信息提取出来,组成一个版本的文件。 按照我的理解用比喻的方式描述。
假设现在写一本书,但是不是线性写作,而是多个章节同时开始,内容写在一个活页本上。
第一天分别写了一二三节的开头,写在三页纸上,这三页纸有各自的名字,暂且称为a, b, c。再用一张小纸条,记录内容是a, b, c是第一个版本的内容,这个小纸条也有个名字,暂称为A。把它们放进活页本里。
第二天重写了第二节,写在新的一张纸上,这张纸名字是d。同样的,有另一张小纸条,记录内容是a, d, c是第二个版本的内容,这个小纸条的名字记为B。再把它们放进活页本里。
这样,我们就有A, B两个版本了。
##目标的实现
沿用上面的比喻,接下来是一些额外的结构,来使用上述思路实现目标。
首先是分支。其实分支就只是又一个小纸条,贴在A, B这样的小纸条上。比如我是书的主要作者,我在B上贴一个main。我的合作者在A的基础上重写了第三节,写在e这张纸上,并且有个C记录a, b, e,在C上就可以有一个dev的小纸条,这就是dev分支。
保证版本内容的可信性,有2个细节。第一,名字a, b, c和A, B, C其实是sha1,这样可以确保内容和名称匹配。第二,B, C上除了内容,其实还包括它的上一个版本,也就是说B还记录了A的名字,这就保证了历史的可信性。
除此之外,git还使用了内容寻址的存储方式。这张纸a的文件名就是a,而a是内容的sha1,所以不同内容的纸不会在这里,很容易检验信息的真实性。
至于分布式,由于分支只是一个小标签,这就自动满足了。