+-
你真的会用 Git 吗?Git 中的数据结构与对应伪代码
首页 专栏 linux 文章详情
0
头图

你真的会用 Git 吗?Git 中的数据结构与对应伪代码

Chris 发布于 5 月 14 日
Git 拥有一个经过精心设计的模型,这使其能够支持版本控制所需的所有特性,例如维护历史记录、支持分支和促进协作。然而,通过自顶向下的方式(从命令行接口开始)学习 Git 可能会让人感到非常困惑。一旦出现问题,就只能将当前工作保存下来,然后重新复制一份工作,继续进行处理了。如果我们能够先对其底层的数据结构有所了解,在接触命令行接口时,就会更加得心应手。

快照

Git 将顶级目录中的文件和文件夹作为集合,并通过一系列快照来管理其历史记录。在 Git 的术语里,文件被称作 Blob对象(数据对象),也就是一组数据。目录则被称之为“树”,它将名字与 Blob 对象或树对象进行映射(使得目录中可以包含其他目录)。快照则是被追踪的最顶层的树,快照也被称为提交(commit)。

历史记录建模:关联快照

在 Git 中,历史记录是一个由快照组成的有向无环图。每个快照都有一系列的“父辈”,也就是其之前的一系列快照。注意,快照可能同时有多个“父辈”,例如,经过合并后的两条分支。

o <-- o <-- o <-- o <---- o ^ / \ v --- o <-- o

数据模型及其伪代码表示

通过伪代码的表示,能够更加清晰的了解 Git 的数据模型。

// 文件就是一组数据 type blob = array<byte> // 一个包含文件和目录的目录 type tree = map<string, tree | blob> // 每个提交都包含一个父辈,元数据和顶层树 type commit = struct { parent: array<commit> author: string message: string snapshot: tree }

对象和内存寻址

Git 中的对象可以是 blob、树或提交:type object = blob | tree | commit,所有的对象都会通过 SHA-1 哈希进行寻址。

objects = map<string, object> def store(object): id = sha1(object) objects[id] = object def load(id): return objects[id]

引用

给这些哈希值赋予人类可读的名字,也就是引用(reference)。引用是指向提交的指针。与对象不同的是,它是可变的(引用可以被更新,指向新的提交)。例如,master 引用通常会指向主分支的最新一次提交。

references = map<string, string> def update_reference(name, id): references[name] = id def read_reference(name): return references[name] def load_reference(name_or_id): if name_or_id in references: return load(references[name_or_id]) else: return load(name_or_id)

在 Git 中,我们当前的位置有一个特殊的索引,它就是 “HEAD”。

git tools linux 开发 开发工具
阅读 60 发布于 5 月 14 日
收藏
分享
本作品系原创, 采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议
avatar
Chris
6 声望
0 粉丝
关注作者
0 条评论
得票数 最新
提交评论
你知道吗?

注册登录
avatar
Chris
6 声望
0 粉丝
关注作者
宣传栏
目录
Git 拥有一个经过精心设计的模型,这使其能够支持版本控制所需的所有特性,例如维护历史记录、支持分支和促进协作。然而,通过自顶向下的方式(从命令行接口开始)学习 Git 可能会让人感到非常困惑。一旦出现问题,就只能将当前工作保存下来,然后重新复制一份工作,继续进行处理了。如果我们能够先对其底层的数据结构有所了解,在接触命令行接口时,就会更加得心应手。

快照

Git 将顶级目录中的文件和文件夹作为集合,并通过一系列快照来管理其历史记录。在 Git 的术语里,文件被称作 Blob对象(数据对象),也就是一组数据。目录则被称之为“树”,它将名字与 Blob 对象或树对象进行映射(使得目录中可以包含其他目录)。快照则是被追踪的最顶层的树,快照也被称为提交(commit)。

历史记录建模:关联快照

在 Git 中,历史记录是一个由快照组成的有向无环图。每个快照都有一系列的“父辈”,也就是其之前的一系列快照。注意,快照可能同时有多个“父辈”,例如,经过合并后的两条分支。

o <-- o <-- o <-- o <---- o ^ / \ v --- o <-- o

数据模型及其伪代码表示

通过伪代码的表示,能够更加清晰的了解 Git 的数据模型。

// 文件就是一组数据 type blob = array<byte> // 一个包含文件和目录的目录 type tree = map<string, tree | blob> // 每个提交都包含一个父辈,元数据和顶层树 type commit = struct { parent: array<commit> author: string message: string snapshot: tree }

对象和内存寻址

Git 中的对象可以是 blob、树或提交:type object = blob | tree | commit,所有的对象都会通过 SHA-1 哈希进行寻址。

objects = map<string, object> def store(object): id = sha1(object) objects[id] = object def load(id): return objects[id]

引用

给这些哈希值赋予人类可读的名字,也就是引用(reference)。引用是指向提交的指针。与对象不同的是,它是可变的(引用可以被更新,指向新的提交)。例如,master 引用通常会指向主分支的最新一次提交。

references = map<string, string> def update_reference(name, id): references[name] = id def read_reference(name): return references[name] def load_reference(name_or_id): if name_or_id in references: return load(references[name_or_id]) else: return load(name_or_id)

在 Git 中,我们当前的位置有一个特殊的索引,它就是 “HEAD”。