Git & Github Notes [2] - Git File System

 

数据对象,树对象,提交对象

Git的文件系统是:铁打的对象,流水的引用

Git中只有三种基本对象

  1. 树对象(目录)
  2. 数据对象(文件)
  3. 提交对象(版本)

暂存blog文件对象

假设我的项目里只有三个简单文件,分别是README,test.rbLICENSE

$ git add README test.rb LICENSE

暂存操作会为每一个文件计算校验和(使用我们在 起步 中提到的 SHA-1 哈希算法),然后会把当前版本的文件快照保存到 Git 仓库中(Git 使用 blob 对象 来保存它们),最终将校验和加入到暂存区域等待提交。如下图所示,三个文件提交暂存区之后,.git/objects目录下就会有三个新的blob文件对象,然后这三个文件的校验和会被加入暂存区。 dataObject

使用git rm命令可以删除暂存区的校验和,但不会删除.git/objects目录下的blob文件对象。所以一般提交过暂存区的文件对象就很难彻底丢失。但要通过校验和来找到一个文件很难。但如果文件包含在一次commit中,根据树对象和提交对象的信息,就可以比较容易得找回文件。

提交生成树对象,和提交对象

$ git commit -m 'The initial commit of my project'

当使用 git commit 进行提交操作时,Git 会先计算每一个子目录(本例中只有项目根目录)的校验和,然后在 .git/objects中这些 校验和保存为树对象。随后,Git 便会创建一个 提交对象,它除了包含上面提到的那些信息外, 还包含指向这个树对象(项目根目录)的指针。如此一来,Git 就可以在需要的时候重现此次保存的快照。现在,Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个树对象(记录着目录结构和 blob 对象索引)以及一个提交对象(包含着指向前述树对象的指针和所有提交信息)。如下图所示, treeObject

一个树对象里可以包含指向另一个树对象的指针,这样后者就成了前者的一颗子树。如下图所示, structure0

做些修改后再次提交,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针。 commitHistory

对象就是”快照”,稍有修改就是两个不同对象

Git里不是用文件名来区分文件。同一个文件,修改前后的两个不同版本,对应Git仓库里的两个不同“文件对象”。这就是所谓的“快照”。用来区分文件的签名是SHA-1 哈希算法得到的文件的校验和。这是Git中最聪明的策略。

如下图所示,我原先有个文件text.txt里写了内容version 1。把内容改成version2,但文件名保持text.txt。在 Git仓库里就会有两个blob文件对象,对应text.txt。对一个树对象也是如此。 structure1

这样做,虽然对个别文件来说,稍微一个小改动都会导致整个文件被拷贝一遍,数据会有冗余。但这样的代价非常划算。因为这样可以让每个版本完全抽象成文件快照指针组成的一棵树。这让创建新的分支的开销变得非常小。

`