1. 近乎所有操作都是本地执行
在 Git 中的绝大多数操作都只需要访问本地文件和资源,不用连网。但如果用 CVCS 的话,差不多所有操作都需要连接网络。因为 Git 在本地磁盘上就保存着所有当前项目的历史更新,所以处理起来速度飞快。
2. 时刻保持数据完整性
在保存到 Git 之前,所有数据都要进行内容的校验和(checksum)计算,并将此结果作为数据的唯一标识和索引。换句话说,不可能在你修改了文件或目录之后,Git 一无所知。这项特性作为 Git 的设计哲学,建在整体架构的最底层。所以如果文件在传输时变得不完整,或者磁盘损坏导致文件数据缺失,Git 都能立即察觉。
Git 使用 SHA-1 算法计算数据的校验和,通过对文件的内容或目录的结构计算出一个 SHA-1 哈希值,作为指纹字符串。该字串由 40 个十六进制字符(0-9 及 a-f)组成,看起来就像是:
24b9da6552252987aa493b52f8696cd6d3b00373
Git 的工作完全依赖于这类指纹字串,所以你会经常看到这样的哈希值。实际上,所有保存在 Git 数据库中的东西都是用此哈希值来作索引的,而不是靠文件名。
3. 多数操作仅添加数据
常用的 Git 操作大多仅仅是把数据添加到数据库。因为任何一种不可逆的操作,比如删除数据,都会使回退或重现历史版本变得困难重重。在别的 VCS 中,若还未提交更新,就有可能丢失或者混淆一些修改的内容,但在 Git 里,一旦提交快照之后就完全不用担心丢失数据,特别是养成定期推送到其他仓库的习惯的话。
4. 快照
git在正确的抽象层次上处理存储空间压缩,使得程序比上代(如svn)和同时代(如bzr)的VCS大为简化。
之前的VCS从节省空间出发,想当然地把delta作为基础数据结构。这样的最大问题(远不是唯一问题)是:delta设计时没有考虑到的修改方式就无法表达。例如,svn早期版本及更早的VCS不能记录文件rename/copy,所以只要重命名文件,列出历史时重命名之前的历史就显示不出来。
git的存储层(plumbing layer)提供的接口里,每个commit都记录完整的目录树。存储空间压缩问题完全在存储层内部解决:
- 逻辑上,存储层是一个CAS(Content-Addressable Storage)。这意味着在一个commit中,所有没改变的文件和目录都不额外占用存储空间。进一步,两个目录中内容相同的文件也只占用一份存储空间;甚至,两个文件的任意两个历史版本只要内容相同,就只占用一份存储空间。这是基于delta的VCS做不到的。
- 而对于同一个文件的历史版本的压缩,git的做法是把全部文件的历史版本统一处理,把文件间相同的片段进行压缩。这意味着两个不相干的文件中相同的片段也可以被压缩。这是基于delta的VCS做不到的。