Synth Daily

从 CVS 到 Git,三十年的版本控制变迁

这篇内容回顾了源代码管理工具三十年来的演变,从早期的 ZIP 文件备份,到 RCS 和 CVS 的锁模式与并发尝试,再到 Subversion 对 CVS 缺陷的修复。文章的核心论点是,这些早期的中心化工具都存在根本性缺陷,直到 2005 年 Linus Torvalds 因商业工具 BitKeeper 撤销许可,在十天内创造出 Git,才真正以其分布式模型解决了单点故障、离线工作和分支合并的难题。最终,GitHub 平台通过其社交化的协作流程将 Git 推向了行业标准地位,尽管存在新兴替代品,但 Git 的核心地位在可预见的未来依然稳固。

版本控制之前的混沌时代

在 2010 年之后入行的开发者可能无法想象当时的情况有多糟糕。了解这些背景有助于理解后续系统为何如此设计。

  • ZIP 文件归档: 项目以日期命名,如 project-2003-04-15.zip。开发者需要手动在成堆的压缩包里寻找“可用的版本”。
  • 手动命名版本: 在共享文件夹里,文件名充满了 FINAL, FINAL_v2, FINAL_REALLY 这样的绝望标记。
  • 物理或口头锁定: 通过白板或邮件通知同事“我正在编辑某个文件,别碰它”,这是 90 年代许多公司的普遍做法。
  • 个人备份: 每个开发者都依赖软盘来保存自己“可用的版本”,这实质上是个人版的网络共享。

在正式的版本控制出现之前,每个开发者都维护着自己那套临时且不可靠的系统。

锁模式时代:SCCS 与 RCS

最早的正式版本控制系统来自贝尔实验室和早期的 Unix 社区,它们引入了“锁”的概念。

  • SCCS (1972): 基于文件、单用户、锁模式。编辑文件前需要锁定,其他人无法操作。
  • RCS (1982): 改进了差异存储和版本追踪,但本质上仍是锁模式。一次只能锁定和编辑一个文件,没有项目的概念。

这个时代为版本控制贡献了核心词汇,如 差异 (Deltas)检出 (Check-out)检入 (Check-in)。但锁模式严重制约了团队协作。

CVS:糟糕的并发编辑与服务器时代

CVS 大约在 1990 年到 2005 年间主导了开源世界,因为它解决了锁模式的最大痛点。

  • 核心创新: 允许多个开发者同时编辑同一个文件,并在提交时尝试合并。
  • 致命缺陷:
    • 没有原子提交: 如果提交多个文件时网络中断,代码库会进入不一致的“半提交”状态。
    • 分支与合并是噩梦: 创建分支非常缓慢,合并则极易出错且需要大量手动操作。
    • 无法追踪重命名和目录结构: 移动文件等于删除旧文件再添加新文件,历史记录完全丢失。
    • 中心化且脆弱: 所有历史记录都存在于一台服务器上,硬盘损坏意味着一切都消失了。

每个在那个年代使用 CVS 的人都有一堆关于合并冲突和代码库损坏的故事。它之所以流行,仅仅是因为它是免费的,并且没有更好的替代品。

Visual SourceSafe:微软生态的平行世界

在 Unix 世界使用 CVS 的同时,Windows 开发者大多生活在 Visual SourceSafe (VSS) 中。VSS 默认采用悲观锁模式:一人检出文件,其他人只能只读等待。

最臭名昭著的问题是数据库损坏。VSS 的数据存储在网络共享的 .dat 文件中,非常脆弱。

“VSS 数据库已损坏,请运行分析工具,如果不行就从昨晚的备份中恢复。”—— 这在当时的微软技术栈公司中,是标准的 IT 操作流程,而非最坏情况的预案。

由于与 Visual Studio 捆绑,VSS 尽管问题重重,依然长期存在。

Subversion:“正确的 CVS”

Subversion (SVN) 在 2000 年启动,目标明确:成为一个“做对了的 CVS”。它在 2004 年发布 1.0 版本,并迅速成为 CVS 的替代者。

  • 修复的要点:
    • 原子提交: 多文件提交要么完全成功,要么完全失败,代码库始终保持一致。
    • 真正的分支与标签: 创建分支和标签变得非常廉价和快速。
    • 追踪目录和重命名: 项目的结构也被纳入了版本控制。
  • 未解决的根本问题:
    • 依然是中心化模型: 没有网络就无法提交。服务器宕机,整个团队停摆。

SVN 几乎赢得了胜利,直到两年后 Git 的出现。

2005 年 4 月:版本控制的永久变革

这个故事值得每个开发者了解。Linux 内核项目曾使用一个名为 BitKeeper 的专有分布式版本控制系统 (DVCS)。2005 年 4 月,其免费许可因社区成员试图逆向工程其协议而被撤销。

世界上最大的协作软件项目,突然之间没有了版本控制系统。

Linus Torvalds 从 4 月 3 日开始编写一个新的替代品。十天之内,他拿出了一个可用的工具,这个工具就是 Git。它的设计理念完全源于对之前所有系统缺陷的清醒认识:

  • 完全分布式: 每个克隆都是一个完整的代码库,包含全部历史,没有单点故障。
  • 速度极快: 足以应对 Linux 内核这样庞大的项目。
  • 内容寻址的数据模型: 所有对象都通过其内容的 SHA-1 哈希值来标识,这使得数据损坏可以被立即检测到。
  • 廉价的分支: 分支仅仅是一个指向提交的指针,创建和切换分支是瞬间完成的操作。

Git 不是演进的结果,而是一次彻底的革命,它由一位被逼到墙角的开发者在两周内完成。

GitHub:将 Git 推向行业默认的平台

Git 工具的成功归功于 Linus,但其文化上的统治地位则归功于 GitHub。

GitHub 于 2008 年推出,它带来的不仅仅是代码托管,更是一种全新的协作模式:拉取请求 (Pull Request)。它将分支、审查、合并等操作变得可视化、可点击且带有社交属性。开源贡献的门槛降低为“拥有一个 GitHub 账户”,网络效应迅速形成。

如果没有 GitHub,Git 在技术上可能仍会胜出,但它不会成为今天这样无处不在的文化默认。

Git 的现状与未来

Git 已经统治了这个领域。所有主流代码托管平台都基于 Git。虽然出现了一些值得关注的挑战者,如 Meta 的 Sapling、Google 的 Jujutsu 和理论更严谨的 Pijul,但它们在未来十年内都难以取代 Git 的地位。

Git 的核心数据模型已经存在了二十多年,并且没有真正的替代方案出现。

同时,Git 本身并非没有风险。即便是经验丰富的用户,也可能因误用 git checkout 等破坏性命令而丢失工作。但这说明了 Git 现存的风险大多属于用户操作失误,而非平台设计缺陷,这本身就是一种巨大的进步。