git 学习简记 2

(这篇简记源自阅读 The Architecture of Open Source Applicationsgit 一文)

对象数据库

git 包含四种对象类型。每种对象类型均包含 类型大小,以及 内容 字段:

git objects

  • :树中的元素可以是树,也可以是文件对象
  • 文件对象:对于代码库中存储的文件
  • 提交:提交指向代表该提交顶层目录的树
  • 标签:标签包含其名称,指向某个提交

所有的对象均由 SHA (40 位的对象标识) 所引用,这意味着:

  1. 如果两个对象相等,那么它们的 SHA 值也相等
  2. 如果两个对象不等,那么他们的 SHA 值也不等
  3. 如果对象在拷贝时数据遭到损毁,那么通过计算它的 SHA 值可以定位该损毁

1.2. 构成了 git 分布式模型的基础;3. 保证了文件完整性。

存储和压缩机巧

为了节省空间,git 将对象打包成一种压缩格式,利用索引文件指向每个被打包文件所对应的偏移,以进行解包:

packed format

git count-objects 可以计算出打包对象的数量

git 的打包机制在不断进化:最初 git 通过存储打包文件的 CRC 校验和来保证文件完整性,但重打包文件时并不会做进一步检查。之后的版本 git 会保存每一个压缩对象的 CRC 校验和,并支持打包大于 4 GB 的文件。

合并历史

在处理合并历史的方式上,git 和其它基于 RCS 的 VCS 有着本质的不同。

以 Subversion 为例,它把文件或树历史表示为一个线性过程,高版本号会覆盖低版本号。它不直接支持分支,只能通过目录结构来间接支持。

在使用 Subversion 时,假设我们在分支 branches/branch-name 进行了一系列工作,然后想把这些工作合并回 trunk 目录。这里的问题在于由于 Subversion 使用线性历史,我们无法直接得知 trunk 中是否包含其它分支中的改动。

对于基于 DAG 的 git,种种情形就很好应付:我们可以开 branch-name 分支进行相应改动,然后将 branch-name 合并到 master 分支(对应 Subversion 中的 trunk 概念),历史纪录一目了然。

merge history

然而基于 DAG 的合并仍存在问题,例如,我们在前例中假设我们的合并包含两个分支中的所有改动,但实际可能不是这样。

展望

  • git 需要提供 IDE 友好的库以便与各个 IDE 集成(libgit2, JGit
  • git 没有被很好的移植到 Windows

经验 教训

  • git 的对象数据模型很好的解决了分布式版本管理问题
  • 早期 git 命令直接使用了 shell 脚本,这使得 git 难以被移植到其他系统,尤其是 Windows
  • git toolkit 包含大量命令,容易(尤其是底层命令)对初学者造成困扰

(完:这篇简记源自阅读 The Architecture of Open Source Applicationsgit 一文)