Git 的快照哲学:不是增量,是内容寻址

很多人把 Git 当"高级保存"用。但 Git 的设计哲学和 SVN 完全不同——它不是记录「改了什么」,而是记录「这一刻所有文件的完整状态」。


问题从哪里来

传统版本控制(CVS、SVN)是增量模型:只存 diff,版本是一条链。

这导致:

  • 回滚到旧版本,要反向应用所有 diff——慢
  • 分支操作,要算「从哪分出来的」——复杂
  • 合并冲突,要三方 diff——容易错

Git 想清楚了:与其算 diff,不如直接存快照


快照模型是什么

每次 git commit,Git 做的事:

HEADSHA-1

关键:Git 不是「版本控制系统」,是**「内容寻址文件系统」**——

  • 文件内容 → 哈希(地址)
  • 哈希(地址)→ 文件内容

这就是 .git/objects/ 里那些怪文件名的来源——它们就是哈希值


这个设计带来的能力

能力为什么快照模型能做到增量模型做不到
分支切换秒级只是把 HEAD 指向另一个快照要算 diff、应用补丁
离线工作所有历史都在本地快照里得连服务器才能看历史
Cherry-pick直接取那个快照里的文件状态要算「这个 commit 改了什么」
合并三个快照比对,不是算 diff增量合并容易漏

认知升华

回头看,Git 教给我们的是:

不要用「增量思维」解决所有问题。

有时候,存「完整状态」比存「变化」更高效——因为状态是确定的,变化是相对的。

这和函数式编程的「不可变数据」是一个道理:存值,不存改


验证你有没有想清楚

两个问题:

  1. Git 的「快照」为什么不会让仓库变得巨大?(git gc 之前和之后,存储方式有什么不同?)
  2. 为什么 Git 的「内容寻址」让「去重」天然高效?换一个文件的位置(比如从 a/b.js 移到 src/b.js),Git 怎么处理?

(答案同样不写在这里——去想清楚,想清楚了才是你的认知。)