我会尽量简短。在Git 的俄语文档站点上,给出了它如何工作的以下解释:
Git 将存储的数据视为小型文件系统的一组快照。每次您签入项目的当前版本时,Git 基本上都会保存项目所有文件在当前时间的样子的快照。为了效率,如果文件没有改变,Git 不会再次保存文件,而是链接到之前保存的文件。
所以,如果我们非常粗略地假设一个文本文件的大小趋向于 1Mb,那么按照 Git 的逻辑,即使是这个文件中最小的变化(单词中的错误已被纠正)都会创建一个“cast”(=copy ) 的文件,大小约为 1Mb。
问题:这对使用的内存有多大好处,或者文本文件是否以某种方式分成更小的文件,并且它们已经受到“强制转换”的创建?

简而言之:上图是对观察到的 GIT 行为的解释。如果您使用标准命令使用 GIT 并且不进入二进制文件,那么一切看起来都像这样工作。但这并不意味着文件的每个版本都会真正花费一兆字节......
因为在较低级别,git 仍然使用文件之间的增量。你可以在这里阅读它们:Inside Git - Pack files
但是,文件并不总是被打包,只有在达到解压对象数量的某个阈值或提交被推送到远程存储库时才会打包。如果您有大文件,在某些情况下,您必须显式执行一个命令
git gc来重新打包所有 blob(例如,我们曾经必须将此命令添加到构建脚本中,因为在构建服务器上,发送到远程存储库永远不会发生,并且本地存储库不受控制地增长)。这正是“Git Inside - Pack Files”所讲述的内容。其实这个问题是有答案的:
也就是说,在存储库运行一段时间后,文件的不同版本将最终在一个 Pack 文件中,它以一种更有效的方式表示不同的版本:通过基础和增量(差异,更改)。
不,文件(与任何其他对象一样,例如,文件夹 - “子对象的名称 - 它的哈希”对的列表)被完整保存。顺便说一句,这增加了存储库的“生存能力”——如果由于某种原因某些对象被损坏或删除,那么恢复的可能性仍然非常高,如果不是最后一次提交,那么至少有一个最后一次提交.
但是,与对象存储 (
./git/objects) 并行的还有一个压缩文件,其中所有对象.git/objects/pack/以差异的形式存储在一个打包文件 ( ) 中。任何对象都可以放在那里,而对象的原始文件被删除。由于打包操作非常耗时,因此只有在调用命令时才会执行
git gc --force。同时,存储库中的任何进一步更改(添加提交和重写历史记录)将继续将对象添加到主存储库;在第二种情况下,tails 也将保留在包文件中,只有在下次调用git gc.有一些关于 git 的好文章(例如,示例)揭示了 git 的内部结构。
下面显示了文件更改时发生的机制。
您可以查看对象文件夹中的文件并使用 git cat-file -p 命令查看文件的解压缩表示。
这是单个文件级别的机制。这似乎 - 次优消费。然而,还有一个额外的机制——当对象被打包成更大的文件时。
存储大文件的问题也导致了LFS的引入。事实是,你甚至从未编辑过的大文件(图片类型的二进制文件)真的很难保存在 git 中,因此它们被保存到单独的文件存储中。