Skip to content
字数
1179 字
阅读时间
5 分钟

版本控制系统

版本控制系统(VCSs)是一类用于追踪源代码(或其他文件、文件夹)改动的工具。它的核心作用包括:

  • 管理代码的修改历史
  • 协作编码更方便。

VCS通过“快照”机制工作:将某个文件夹及其内容的完整状态保存为快照,同时还会维护快照创建者、快照相关信息等。

实用性

无论单人开发还是团队协作,VCS都很有用:

  • 单人开发时:可创建项目快照,记录每个改动的目的,支持多分支并行开发等;
  • 团队协作时:能查看他人对代码的修改,还可解决“并行开发引发的冲突”,是协作的“无价之宝”。

现代版本控制系统的能力能轻松(甚至自动)回答这类问题:

  • “当前模块是谁编写的?”
  • “这个文件的某一行,什么时候被编辑?谁改的?修改原因是什么?”
  • “最近1000个版本中,何时/为什么导致了单元测试失败?”

Git

尽管版本控制系统有很多,但Git是事实上的行业标准。文中还提到,一篇“XKCD漫画”反映了人们对Git的评价。

Git 接口存在 抽象泄漏(leaky abstraction) 问题,接口虽“丑陋”,但 底层设计和思想非常优雅,容易被理解。

Git 的数据模型

Git通过精心设计的数据模型,支持版本控制的关键特性:维护历史记录、支持分支开发、促进团队协作

快照(文件与目录的Git表述)

Git将“顶级目录的文件/文件夹”视为集合,通过快照管理历史。其中涉及:

  • Blob对象:Git中“文件”的表述,本质是“一组纯数据”(仅存储文件内容)。
  • “树”(Tree):Git中“目录”的表述,负责映射“名字”与 Blob对象(文件)或其他树对象(子目录)(因此目录可嵌套子目录)。
  • 快照:被追踪的最顶层“树”,代表某一时刻项目的“完整文件结构”。

顶层树结构示例

<root> (tree)
|-- foo (tree)
|   |-- bar.txt (blob, contents = "hello world")
|-- baz.txt (blob, contents = "git is wonderful")

顶层树(<root>)包含两个元素——子树foo(内部含Blob对象bar.txt)、直接的Blob对象baz.txt

历史记录建模:快照的关联方式

版本控制系统需将“快照(某一时刻的项目状态)”串联为历史。线性历史是最简单的模型(快照按时间顺序排成一条线),但 Git 并未采用这种方式。

Git 的历史是 由“快照”(在 Git 中称为「提交」)组成的有向无环图

  • 无需纠结“有向无环图”的数学概念,核心理解:每个「提交」都有 “父辈”提交(即它“之前”的快照)。
  • 一个提交可以有 多个父辈(典型场景:分支合并后,新提交会同时关联两个分支的“父提交”)。
o <-- o <-- o <-- o
            ^
             \
              --- o <-- o
o <-- o <-- o <-- o <----  o 
            ^            /
             \          v
              --- o <-- o
  • 图中 o 代表一次「提交(快照)」,箭头指向“当前提交的父辈”(表示“时间/因果上的先后:父辈在当前提交之前”)。
  • 体现了 分支与合并 的场景:
    • 第三次提交后,历史“分岔”为两条独立分支(可用于并行开发不同特性);
    • 开发完成后,分支“合并”产生新提交——这个新提交会同时包含两个分支的特性,且有多个父辈(来自两条分支的最后一次提交)。

Git 中的提交是不可改变的。但这并不代表错误不能被修改,只不过这种“修改”实际上是创建了一个全新的提交记录。而引用(参见下文)则被更新为指向这些新的提交。

贡献者

文件历史

Written with