54

据此:_

需要注意的是,这与您可能熟悉的大多数 SCM 系统非常不同。Subversion、CVS、Perforce、Mercurial 等都使用 Delta 存储系统——它们存储一个提交和下一个提交之间的差异。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动态计算差异?

4

2 回答 2

87

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

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

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

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

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

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

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

However, when Git runs its garbage collection (or when you call git gc manually), then the duplicates are cleaned up and a read only pack file is created. You don't have to worry about running garbage collection manually - git contains heuristics which tell it when to do so.

于 2014-07-30T04:16:50.107 回答
55

不,git 中的提交对象不包含差异 - 相反,每个提交对象都包含树的哈希,它递归且完整地定义了该提交时源树的内容。git community book 中有一个很好的解释,说明了blob objects、tree objects 和 commit objects 的内容。

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

于 2012-05-01T14:10:04.780 回答