版本控制(Git)¶
约 693 个字 预计阅读时间 2 分钟
git 的数据模型¶
- 快照(snapshots)
- git 将顶级目录中的文件和文件夹作为集合,并通过一系列快照来管理其历史记录。
- 文件被称作 blob 对象(数据对象),也就是一组数据。
- 目录(directory)被称作树,它将名字与 blob 对象或树对象进行映射。不是很懂。
- a snapshot is the top-level tree that is being tracked.
<root> (tree)
|
+- foo (tree)
| |
| + bar.txt (blob, contents = "hello world")
|
+- baz.txt (blob, contents = "git is wonderful")
In the above example, the top-level tree contains two elements, a tree "foo" (that itself contains one element, a blob "bar.txt"), and a blob "baz.txt".
-
Modeling history: relating snapshots
- 在 git 中,历史记录是一个由 snapshot 组成的有向无环图。(每个 snapshots 都有一系列之前的 snapshot,某些 snapshot 可能由多个 parents 而来,例如经过合并后的两条分支)
- 这些 snapshot 被称为 commit。
- 可视化:
- 箭头指向当前 commit 的 parent (这里的箭头表示“在……之前”的关系)。可以看到第三次提交之后,历史记录分岔成了两条独立的分支。(这可能因为此时需要同时开发两个不同的特性,它们之间是相互独立的)。开发完成后,这些分支会被合并并创建一个新的 commit, 新的 commit 创建一个新的历史记录。
-
数据模型及其伪代码表示
type blob = array<byte> // 文件就是一组数据
type tree = map<string, tree | blob> // 一个包含文件和目录的目录
type commit = struct {
parents: array<commit>
author: string
message: string
snapshot: tree
}
//每一个提交都包含一个父辈,元数据和顶层树
-
对象和内存寻址
- git 中的对象可以是 blob, tree 和 commit
type object = blob | tree | commit
- git 在存储数据时,所有的对象都会基于它们的 sha-1 哈希进行寻址。
objects = map <string, object> def store(object): id = sha1(object) objects[id] = object def load(id): return objects[id]
- 当它们引用其它对象时,它们并没有真正在硬盘上保存这些对象,而是仅仅保存了它们的哈希值作为引用。
- 引用
- 现在我们所有的 snapshot 都可以通过它们的 SHA-1 哈希值来标记。但是因为这是一个 40 位的十六进制串,很不方便。
- 所以 git 将这些哈希值赋予人类可读的名字,也就是引用。
- 引用是指向 commit 的指针。引用是可变的 (引用可以被更新,指向新的 commit)
- 这样 git 就可以使用诸如 master 这样可读的名称来表示历史记录中某个特定的提交。
-
仓库
- git 仓库的定义:对象和引用
- 在硬盘上,git 仅存储对象和引用。所有 git 命令都对应着提交树的操作,例如增加对象,增加或删除引用。
暂存区¶
staging area: 允许我们指定下次 snapshot 中要包括哪些改动。
命令行接口¶
git log
: 显示历史日志git log --all --graph --decorate
: 可视化历史记录(有向无环图)git diff <filename>
: 显示与暂存区文件的差异。git diff <revision> <filename>
显示某个文件两个版本之间的差异git checkout <revision>
更新 head 和目前的分支。
最后更新:
2024年10月21日 12:15:10
创建日期: 2024年10月21日 12:15:10
创建日期: 2024年10月21日 12:15:10