构建高效版本控制,无需重复存储文件
为每个版本或分叉(fork)存储文件的完整副本会浪费空间。如果你在一个包含十个文件的项目中只修改了一行,你不应该再次保存所有十个文件。
在构建我的 LaTeX Writer 项目时,我遇到了这个问题。我需要一种既能处理版本控制和项目分叉,又不会产生高昂存储成本的方法。
我研究了 GitHub 的工作原理。GitHub 并不会在你每次做出更改时都存储整个仓库。它将内容分开存储,并使用引用来链接文件和提交(commits)。
我使用三个主要组件构建了我的系统:
- 元数据 (Metadata):存储项目、所有者和文件夹的 ID。
- 文件记录 (File Records):存储文件名以及指向内容的链接。
- Blobs:实际内容存储的地方。
该系统通过内容哈希(content hashing)工作。当你保存一个文件时,系统会根据内容生成一个唯一的 ID。如果内容已经存在,系统会重用现有的 Blob,而不会创建新的。
这种方法让分叉(forking)变得既简单又廉价。当你分叉一个项目时:
- 系统会创建一个新的项目 ID。
- 它会为文件和文件夹创建新的元数据。
- 它将新的元数据指向现有的 Blobs。
在分叉过程中,没有任何实际的文件内容被复制。你只需要复制少量的元数据记录。
当你编辑一个分叉时,过程依然保持高效:
- 你修改了内容。
- 系统对新内容进行哈希处理。
- 只有在完全相同的内容不存在时,才会创建一个新的 Blob。
- 你分叉项目的元数据会指向新的 Blob。
- 原项目仍然指向旧的 Blob。
这种方法具有以下几个优点:
- 内容去重可以节省大量空间。
- 分叉几乎是瞬间完成的。
- 版本管理保持井然有序。
- 数据库增长缓慢。
你可以获得类似 GitHub 的功能,而不会带来沉重的存储开销。