0%

Git本地文件管理

Git文件存储

Git将历史文件、快照等信息存储在工作区根目录的.git/objects目录下。objects用于存放镜像和实际文件等信息,其内部文件分为三种类型,分别为:

  • Blob:用于文件,将文件内容压缩成二进制文件后进行存储。

  • Tree:用于文件夹,存储的内容为文件夹下的文件类型、文件名和文件哈希值等,同样是使用二进制压缩存储。

  • Commit:代表快照,包含该快照所包含的文件和一些控制信息等,使用二进制压缩存储。

同时,Git将这些文件的哈希值作为分组和标识的依据。具体来说,将文件放置在以文件哈希值的前两位命名的文件夹中,并使用文件哈希值除前两位的部分作为文件名。

Git进行本地管理的过程图解

图中各元素含义如下:

  • 方形:实际存储数据的文件。

  • 菱形:目录,即文件的索引。

  • 圆形:快照文件。

  • 圆角矩形:头指针或分支指针。

  • 实线:被指对象被另一端对象的引用,可以被另一端对象索引查找。

  • 虚线:被指对象是另一端对象的压缩。

接下来给出Git进行本地文件管理的过程对应的图解:

  1. 假设目前项目中只有两个文件,并完成了一次提交,这回生成对应的压缩对象、索引文件、快照文件,并设置好索引和指针。其对应的内部状态如下:

  1. 现在修改其中一个文件,这会丢失文件与压缩对象的对应关系,于是文件变为modified状态。此时内部状态变为:

  1. 现在使用git add添加修改,此时会对其修改文件创建压缩对象,并修改暂存区索引,于是文件变为staged状态。此时内部状态变为:

  1. 现在使用git commit提交修改,这会生成此时的暂存区索引的压缩文件,并创建新的镜像对象,并将其指向上一提交镜像和当前暂存区压缩文件,之后相应的移动头指针和分支指针。此时内部状态变为:

一些常见问题

  1. 修改文件的局部时,是否会存储整个文件?

是的。当修改一个文件的局部时,将会重新生成对应文件的整个文件的镜像,而不是生成文件修改的镜像。

同时,只会新增被修改文件的镜像,而未修改文件不会形成相应的镜像。

因此,Git不适合管理那些经常会进行修改的较大文件,而更加适合对大量的、通常只会做局部修改的较小文件和不经常修改的较大文件进行管理。这符合编程项目的特点——大量较小的编程文本文件,不经常修改的较大的库文件。

  1. 当多次git add同一文件时,是否会生成对应的镜像文件?

视该文件hash是否改变而定。

git add会计算待添加文件的hash,并在当前的文件仓库中进行查找,只有当未找到时才会创建对应的文件。之后会设置相应的索引。

因此若多次添加的文件hash一致时,不会生成对应的镜像文件。甚至如果多个文件的hash相同时也只会生成一个对应的镜像文件。

当多次添加的文件hash不一致时,一般就会生成对应的镜像文件了。