1.2 版本库,分布式工作的基础所在
其实,版本库本质上就是一个高效的数据存储结构而已,由以下部分组成。
文件(即blob):这里既包含了文本也包含了二进制数据,这些数据将不以文件名的形式被保存。
目录(即Tree):目录中保存的是与文件名相关联的内容,其中也会包含其他目录。
版本(即commit):每一个版本所定义的都是相应目录的某个可恢复的状态。每当我们创建一个新的版本时,其作者、时间、注释以及其之前的版本都将会被保存下来。
对于所有的数据,它们都会被计算成一个十六进制散列值(例如像1632acb65b01 c6b621d6e1105205773931bb1a41这样的值)。这个散列值将会被用作相关对象的引用,以及日后恢复数据时所需的键值(见图1.3)。
图1.3 版本库中的对象存储
也就是说,一个提交对象的散列值实际上就是它的“版本号”,如果我们持有某一提交的散列值,就可以用它来检查对应版本是否存在于某一版本库中。如果存在,我们就可以将其恢复到当前工作区相应的目录中。如果该版本不存在,我们也可以从其他版本库中单独导入(拉回)该提交所引用的全部对象。
接下来,我们来看看采用这种散列值和这种既定的版本库结构究竟有哪些优势。
高性能:通过散列值来访问数据是非常快的。
冗余度——释放存储空间:相同的文件内容只需存储一次即可。
分布式版本号:由于相关散列值是根据文件,作者和日期来计算的,所以版本也可以“离线”产生,不用担心将来会因此而发生版本冲突。
版本库间的高效同步:当我们将某一提交从一个版本库传递给另一个版本库时,只需要传送那些目标版本库中不存在的对象即可。而正是因为有了散列值的帮助,我们才能很快地判断相关对象是否已经存在。
数据完整性:由于散列值是根据数据的内容来计算的,所以我们可以随时通过Git来查看某一散列值是否与相关数据匹配。以检测该数据上可能的意外变化或恶意操作。
自动重命名检测:被重命名的文件可以被自动检测到,因为根据该文件内容计算出的散列值并没有发生变化。也正因为如此,Git中并没有专用的重命名命令,只需移动命令即可。