Git 快照 Snapshot
在对 Git 基础的学习过程中,我们了解了 Git 仓库的基本结构:
- 工作目录
- 暂存区
- 版本库,即 .git 仓库
下面我们就通过一次修改、暂存以及提交的工作流程,来理解快照(Snapshot)的概念。
现在,我们在工作目录下新增三个文件:test1.txt
、test2.txt
、test3.txt
。然后,我们执行 git add
将这三个文件暂存。那么,此时这个指令做了哪些事呢?
- 首先,它将这三个文件分别创建3个校验和添加到暂存区中。在前面对 Git 基础的学习中, 我们了解到,校验和是 Git 通过 SHA-1 哈希算法遍历每一个文件并根据文件内容等信息,为文件创建的一个唯一索引。因此,我们可以通过这个唯一索引,取出相应文件的完整内容。
- 然后,Git 对当前的暂存区拍了一张“照片”,即快照,并将快照放入了版本库中。那么快照里面包括哪些内容呢?快照中包括前面所说的唯一文件索引和相应文件的完整内容,其采用类似于 key-value 的结构存储这些信息,同时,Git 使用内置的blob对象来存储这些文件的快照。
暂存修改后,执行 git commit
,这条指令又做了哪些事情呢?
- 首先,Git 通过一个内置的 tree 对象,将文件的目录结构保存下来。
- 然后,Git 在这个 tree 对象上又包裹了一层,创建了一个 commit 对象,这个 commit 对象也是 Git 进行版本管理的最终对象。commit 对象中包含了 tree 对象以及作者、提交描述等信息。
同时,需要注意的是,在 tree 对象中,实际上包含了对快照的引用,即对所有文件索引的引用。
因此,我们可以总结一下快照的概念:
快照就是在执行
git add
和git commit
时,对当前暂存区的情况拍摄的一张“照片“,这个照片中涵盖的若干信息将被存放到git版本库下。这些若干信息包括:
- 文件的索引+文件的完整内容(key-value结构)
- 文件的目录结构
- 提交信息
这三者分别用 Git 内置的 blob,tree,commit 对象进行存储。
接下来,我们再次对test2.txt
文件进行修改,然后再执行git add
和git commit操作:
这里可以看到,在给当前暂存区拍完快照后,Git 发现test1.txt
和test3.txt
的内容没有变化。因此它只把test2.txt
的相关信息存入版本库,并生成了新 tree 和 commit 对象。
同时,旧test2.txt
和新test2.txt
信息是共存在版本库里的。因此 Git 每次照下保存的都是文件的完整信息,而不是文件的差异。
另外,暂存区的内容也不会随着git commit
的完成而消失,因此“把暂存区文件提交上去”这种说法是不准确的,更准确的说法是,暂存区保存着当前待提交的状态,Git 对这个状态拍了照,然后把照片转换成若干信息存入版本库。