git是否在提交对象中存储差异信息?

时间:2012-05-01 13:57:39

标签: git diff

根据this

  

值得注意的是,这与大多数SCM非常不同       您可能熟悉的系统。 Subversion,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动态计算差异?

2 个答案:

答案 0 :(得分:68)

该陈述的含义是,大多数其他版本控制系统过去需要一个参考点才能重新创建当前提交。

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

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

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

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

所以,如果是这种情况,那么git使用的增量压缩在哪里?

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

但是,当Git运行其垃圾收集时(或手动调用git gc)时,将清除重复项并创建只读包文件。您不必担心手动运行垃圾收集 - git包含启发式操作,告诉它何时执行此操作。

答案 1 :(得分:39)

不,git中的提交对象不包含差异 - 相反,每个提交对象都包含树的哈希值,它以递归方式完全定义该提交时源树的内容。对于blob对象,树对象和提交对象有一个nice explanation in the git community book

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