gpt4 book ai didi

git - 为什么 git 在 'git add' 命令之间生成新的 blob?

转载 作者:行者123 更新时间:2023-12-04 14:20:39 26 4
gpt4 key购买 nike

所以我最近发现了工具 git cat-file 并且一直在使用它。我知道 git 使用 blob 来存储实际内容。但是,为什么每次我 git add 对文件进行更改时,它似乎都会创建一个新的 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 blob 中挖掘,我什至无法取回我的中间更改 abc123。

最佳答案

But why does it seem to create a new blob every time I git add a change to a file, i.e. as opposed to editing the existing blob, or making a new blob and deleting the old one?

任何 blob 都无法更改。这与关于提交的规则相同:任何提交都不能更改。

原因是每个 Git 对象(blob 和提交是四种内部 Git 对象中的两种)的哈希 ID 只是存储为该对象的内容的加密校验和。对于文件(“blob”),实际内容是五个 ASCII 字符 blo bspace,然后是十进制化的 blob 的大小,也存储在 ASCII 中,然后是一个 ASCII NUL 字节,然后是存储的数据。例如,hello 存储为 Python 可能表示为 b"blob 5\0hello"

(您可以使用 SHA1 哈希器或使用 git hash-object 计算此哈希值:

$ echo -n hello | git hash-object --stdin
b6fc4c620b67d95f953a5c1c1230aaab5db5a1b0

或:

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

因此,任何具有哈希 ID b6fc4c620b67d95f953a5c1c1230aaab5db5a1b0 的 blob 都必然是文件 hello,否则——如果不是——你不能存储包含 hello (没有换行符)在此 Git 存储库中。为某个文件找到一个分身(一个阻止存储其他文件的邪恶双胞胎)是不平凡的:参见 How does the newly found SHA-1 collision affect Git?了解详情。

因此,当您git add 一个文件时,Git 会创建一个新的 blob,或者重新使用现有的 blob,这取决于该文件的数据是否已经作为一个文件存在存储库中的 blob。如果您随后 git commit,Git 会永久保存内容,并与新的提交对象相关联。如果您从未提交该 blob 并且也没有其他提交或其他实体引用它,Git 最终会通过其垃圾收集过程使该 blob 过期(请参阅 git gc)。

(请注意,这些 Git 对象也是 zlib 压缩的,并且是所有四种 Git 对象类型的倒数第二个存储形式。但是,一段时间后,现有对象可能会被打包成一个 pack 文件,它们在 zlib-deflated 之前针对其他对象进行增量压缩。pack 文件是最终的存储形式。打包的对象可以在必要时解包,但在正常操作中 Git 只会提取解压缩的对象 扩展增量压缩时从打包文件中即时获取数据。)

(为了完整起见,其他两种 Git 对象类型是带注释的标签。树对象存储文件名称,映射自名称到 blob 哈希 ID,以及文件的可执行位。提交对象通过哈希 ID 引用代表快照的树。带注释的标签对象是一种特殊情况的数据结构,它包含另一个 Git 对象的哈希 ID,加上数据负载;在这个数据负载中,您可以存储 GPG 签名或其他数字签名,以及您喜欢的任何其他内容。然后您可以将轻量级标签指向带注释的标签对象,以获取带注释的标签。)

关于git - 为什么 git 在 'git add' 命令之间生成新的 blob?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55424103/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com