git 的文件快照是什么意思?

What's the meaning of git's snapshot of a file?

我正在阅读git basics

Git thinks of its data more like a set of snapshots of a miniature filesystem

我无法理解 git 的快照的含义。 git 是否将整个文件内容存储在每个 snapshot/version 中?例如, 版本 1

#include <stdio.h>
int main()
{
        printf("hello, world");
        return 0;
}

在版本 2 中,我在文件中添加了额外的一行。

#include <stdio.h>
int main()
{
        printf("hello, world");
        printf("hello, git");
        return 0;
}

git 是否会存储全部内容而不是仅存储这两个版本之间的差异(printf("hello, git")) 作为 svn 等?

如果是,那有什么意义呢?

Will git store the entire content rather than store only the difference(printf("hello, git")) between these two versions as svn etc?

Git 存储文件的全部内容。但是当文件没有改变时它不需要额外的 space 。

阅读关于 Git 包文件格式的精彩回答:Are Git's pack files deltas rather than snapshots?

关于 SHA1

文件(和其他东西)以 "blob" 的形式存储。每个字节序列都有自己的 sha1 代码,这对它来说是非常独特的。

下列关于 SHA1 的说法正确的是:

  1. 文件的 SHA1 计算在任何时候都给出相同的结果,OS,Git 版本或实现。
  2. 具有不同名称或路径但内容相同的文件将始终具有相同的 SHA1-s。
  3. 如果两个文件具有不同的 SHA1-s,则它们不相等的概率为 1。
  4. 如果两个文件具有相同的 SHA1-s,则它们相等的概率约为 1 - 1 / 2400(我记得),这与 1 非常相似。

这个系统有什么好处

  1. 可以非常快速地比较修订是否相等。不检查文件内容,只检查它们的 SHA1-s。
    • 当您 push/pull 时,仅传输更改的文件。
    • 立即检查当前更改的状态。
    • 让您跟踪 N 个内容相同的文件,仅取代 Git 中的单个文件。
  2. 在您的工作树中更改修订非常快。
    • 不应用连续补丁
    • 您可以从一个分支中排除提交,将它们拉到另一个分支,更改它们的顺序。

关于差异(和git差异):

您可能已经注意到 git 确实显示了文本文件的差异,指出了添加和删除的行。为了方便起见,这是使用 diff utility 完成的。这也有助于收集贡献统计数据。这用于解决合并冲突。但是尽管如此 Git 仍将文本(和二进制)文件视为单个 blob。

排除git add --patch

有一种方法可以强制 Git 在暂存更改时将文本文件分成块。这对于非常大的文件可能很有用,但对于小文件就没用了。

git add --patch 

Interactively choose hunks of patch between the index and the work tree and add them to the index. This gives the user a chance to review the difference before adding modified contents to the index.

这些是我最喜欢的关于 Git 的插图,来自 Pro Git

Will git store the entire content rather than store only the difference? [... and if so] what's the point?

是的。这就是构建好的 git 历史变得如此简单的原因,而且足够违反直觉,它还可以提高压缩效率。

(编辑:将 lotsa 迂腐和详细阐述归入修订历史)