【问题标题】:does git store diff information in commit objects?git 会在提交对象中存储差异信息吗?
【发布时间】:2012-05-11 01:00:02
【问题描述】:

根据this

请务必注意,这与大多数 SCM 非常不同 您可能熟悉的系统。颠覆,CVS,Perforce, Mercurial 等都使用 Delta Storage 系统 - 他们存储 一次提交和下一次提交之间的差异。 Git 不做 这 - 它存储项目中所有文件的快照 每次提交时看起来像这个树结构。这是一个 使用 Git 时要理解的非常重要的概念。

然而当我运行git show $SHA1ofCommitObject...

commit 4405aa474fff8247607d0bf599e054173da84113
Author: Joe Smoe <joe.smoe@example.com>
Date:   Tue May 1 08:48:21 2012 -0500

    First commit

diff --git a/index.html b/index.html
new file mode 100644
index 0000000..de8b69b
--- /dev/null
+++ b/index.html
@@ -0,0 +1 @@
+<h1>Hello World!</h1>
diff --git a/interests/chess.html b/interests/chess.html
new file mode 100644
index 0000000..e5be7dd
--- /dev/null
+++ b/interests/chess.html
@@ -0,0 +1 @@
+Did you see on Slashdot that King's Gambit accepted is solved! <a href="http://game

... 它输出提交与先前提交的差异。我知道 git 不会将差异存储在 blob 对象中,但它是否将差异存储在提交对象中?还是git show 动态计算差异?

【问题讨论】:

  • 附注:Git 实际上对对象进行增量压缩,但这只是为了压缩。人们有时会将此误解为 Git 存储差异。这里有一些格式的文档:book.git-scm.com/7_the_packfile.html(请记住,它记录的增量之间的对象只是它发现的相似数据块;它们不一定是同一文件的连续版本,尽管它们可能是。当然,增量不是逐行差异。)
  • 从 Jefromi 更新非常相关的链接:git-scm.com/book/en/Git-Internals-Packfiles

标签: git diff


【解决方案1】:

不,git 中的提交对象不包含差异 - 相反,每个提交对象都包含树的哈希,它递归且完整地定义了该提交时源树的内容。在 blob 对象、树对象和提交对象中有一个 nice explanation in the git community book

git 工具向您显示的所有差异都是根据文件的完整内容按需计算的。

【讨论】:

    【解决方案2】:

    这句话的意思是,大多数其他版本控制系统需要一个过去的参考点才能重新创建当前提交。

    例如,在过去的某个时间,基于差异的 VCS(版本控制系统)会存储完整的快照:

    x = snapshot
    + = diff
    History:
    x-----+-----+-----+-----(+) Where we are now
    

    因此,在这种情况下,要在(现在)重新创建状态,它必须检查(x)然后为每个(+)应用差异,直到它到达现在。请注意,永久存储 delta 的效率极低,因此基于 delta 的 VCS 每隔一段时间就会存储一个完整的快照。 Here's how its done for subversion.

    现在,git 不同了。 Git 存储对完整 blob 的引用,这意味着使用 git,只需一次提交就足以在该时间点重新创建代码库。 Git 不需要从过去的修订中查找信息来创建快照。

    那么如果是这样的话,那么 git 使用的 delta 压缩是从哪里来的呢?

    嗯,这不过是一个压缩概念——如果只有很小的一部分发生了变化,那么将相同的信息存储两次是没有意义的。因此,表示已更改的内容,但存储对它的引用,以便它所属的提交(实际上是引用树)仍然可以重新创建而无需查看过去的提交。但问题是,Git 不会在每次提交后立即执行此操作,而是在垃圾收集运行时执行此操作。所以,如果 git 没有运行它的垃圾收集,你可以在索引中看到内容非常相似的对象。

    但是,当 Git 运行它的垃圾回收时(或者当您手动调用 git gc 时),重复项将被清除并创建一个只读包文件。您不必担心手动运行垃圾收集 - git 包含启发式方法,告诉它何时这样做。

    【讨论】:

    • 谢谢你,卡尔。因此,在一个巨大的项目中提交微小的更改并不会用大量冗余副本膨胀存储库(至少从长远来看)?
    • @shuhalo 没错,尽管它比这更好。如果您制作了所有源文件的副本并将它们添加到当前提交中,则 gc 运行后唯一的附加信息将是元数据 - 文件名、路径、作者等。文件本身的实际内容只是指过去来自原始代码的 blob。
    • 对不起,我不明白你的措辞。您能否对以下内容进行编辑:‘嗯,这不过是一个压缩概念——如果只有很小的一部分发生了变化,那么将相同的信息存储两次是没有意义的。因此,代表发生了什么变化’你是说如果在一个 10k 行的文件上,如果我添加一个字符,那么不会生成一个新的哈希?!这对我来说超级不清楚
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多