为什么在 'git add' 命令之间 Git 会创建新的 Blob?

4

我最近发现了工具git cat-file,并正在尝试使用它。我知道git使用blob来存储实际内容。但为什么每次我通过git add命令更改文件时,似乎都会创建一个新的blob,而不是编辑现有的blob或者创建一个新的blob然后删除旧的blob呢?

例如:

touch hello.txt
// change hello.txt to contains 'hello'
git add hello.txt // creates a blob abc123 containing: 'hello'  

// change hello.txt to 'hello world'
git add hello.txt // creates a blob cba321 containing: 'hello world'  

git commit // creates a commit with tree pointing at blob cba321

因此,包含我中间阶段更改的blob(即包含“hello”的blob abc123)的目的并不明显。

就提交而言,hello.txt 直接从“”变为“hello world”,而且如果没有在 git blobs 中挖掘,我甚至无法找回我的中间更改 abc123。

2个回答

3
但是,为什么每次我将更改添加到文件时似乎都会创建一个新的blob,而不是编辑现有的blob或创建一个新的blob并删除旧的blob呢?
没有任何blob可以被更改。这与提交的规则相同:没有任何提交可以被更改。
原因是每个Git对象的哈希ID(blob和commit是四种内部Git对象之一)只是存储为该对象的内容的加密校验和。对于文件(“blob”),实际内容是五个ASCII字符b、l、o、b、空格,然后是十进制表示的blob大小,并以ASCII形式存储,然后是一个ASCII NUL字节,最后是存储的数据。例如,hello被存储为Python可能表示为“b"blob 5\0hello"”。
(您可以使用SHA1 hasher计算此哈希值,也可以使用git hash-object命令:
$ echo -n hello | git hash-object --stdin
b6fc4c620b67d95f953a5c1c1230aaab5db5a1b0

或者:

$ python3
[snip]
>>> import hashlib
>>> hashlib.sha1(b"blob 5\0hello").hexdigest()
'b6fc4c620b67d95f953a5c1c1230aaab5db5a1b0'

任何具有哈希值b6fc4c620b67d95f953a5c1c1230aaab5db5a1b0的blob都必然是文件hello,否则你不能在此Git仓库中存储不含换行符的包含hello的文件(除非它们具有相同的哈希值)。寻找某个文件的替身文件(阻止存储其他文件的邪恶双胞胎)是很棘手的:详情请参见新发现的SHA-1冲突如何影响Git? 所以当你使用git add添加一个文件时,Git会创建一个新的blob,或者根据该文件的数据是否已经作为blob存在于仓库中来重用现有的blob。如果你随后进行git commit,Git会永久保存其内容,并与新的提交对象相关联。如果你从未提交该blob,并且没有其他提交或实体引用它,则Git最终通过其垃圾收集过程(参见git gc)删除该blob。
(注意,这些Git对象也是zlib压缩的,并且是所有四种Git对象类型的倒数第二个存储形式。但是,经过一段时间后,现有对象可能会被打包到一个“pack文件”中,在被zlib解压缩之前,它们会针对其他对象进行增量压缩。pack文件是终极存储形式。如果必要,可以取消打包对象,但在正常操作中,Git只是从pack文件中提取解压缩的对象数据,同时扩展增量压缩。)
(为了完整起见,另外两种Git对象类型是treeannotated tag。Tree对象存储文件名,将名称映射到blob哈希ID,并存储文件的可执行位。提交对象通过哈希ID引用表示快照的树。annotated tag对象是一个特殊情况的数据结构,它包含另一个Git对象的哈希ID以及数据有效载荷;在此数据有效载荷中,你可以存储GPG签名或其他数字签名以及任何其他你喜欢存储的内容。然后,你可以指向注释标签对象,以获取注释标签。)

2
git add 确实创建了 blob,因为索引(或暂存区,它有许多名称...)的目的是准备快照,这将构成下一个提交。
此外,您提到编辑或删除 blob,但这将违反该工具的原则,因为必须能够一致地重现快照,并保持所有引用的 blob 不变。 在某种程度上,您从未修改任何内容,只是添加更多内容和关系。
回答您的最后一点,不,您甚至不能返回到您认为不值得保存的状态。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接