Git使用对象的SHA-1字符串的前2个字符将对象存储到分类文件夹中,这种存储结构的优点是什么?
我认为它无法避免任何潜在的冲突,为什么不将所有对象放入平面文件夹?
答案 0 :(得分:4)
使用以下方法存储文件的原因有多种:
00/f56c0de1c61fdb926e79e8a0a65bd12930c9
25/ec1c55bfb660548a6770238668c4b117d92f
5d/4b01d98f17a9ad9dd1526b49ba39b5aa37a1
63/6f740b6c284ce6685dc17d473a7360ace249
b1/066d178188dde110149a8422ab651b0ee615
b1/a2b7d02b7b0c43530677ab06235382a37e20
da/a3ee5e6b4b0d3255bfef95601890afd80709
主要原因是您可以限制可以存储在文件夹中的文件数量:某些(相当旧的)文件系统不允许您在目录中存储超过64k的文件。如果您对git商店的所有内容进行评估,这个数额相当小。
另外,因为您使用散列算法,所以您几乎可以确定文件夹中没有太多文件:文件应该平均分布在子文件夹中(至少在文件数量增加时) )
我还认为它可能会导致某些文件系统上的性能问题在文件夹中包含太多文件(尽管我并非100%确定)
答案 1 :(得分:4)
松散对象结构(example here和Git Internal - Packfiles)表示对象最初是如何存储在Git中的。
你可以看到approach used elsewhere too (for images database for instance, actually on two levels,但这也适用于Git):
计算图像的SHA-1哈希值,生成其十六进制格式,并使用SHA-1字符串的前两个字符作为第一级目录。
SHA1哈希提供了良好的分布,即使在前几个字符中也是如此,因此可以很好地将文件分发到(相对)平衡的文件夹结构中。 这种简单的方法在每个级别使用不超过256个文件夹。
使用图像的十六进制形式SHA-1有两个非常好的好处:
- 没有名称冲突,
- 即使同一文件上传多次,任何给定文件也只会存储一次。
objects/[0-9a-f][0-9a-f]
新创建的对象存储在自己的文件中 使用sha1对象名称的前两个字符将对象显示在256个子目录上,以将对象本身中的目录条目数保持为可管理的数字。 此处找到的对象通常称为解包(或松散)对象。
git commit 88520ca为我们提供了有关该结构优势的更多信息,这些信息在gc
运行时会受到影响:
搜索4个目录以改进
的统计信息gc
提示在Windows上,
git-gui
建议运行垃圾收集器(如果找到).git/objects/42
中的1个或多个文件(而不是其他文件中的8个文件) 平台)。
如果回购包含大约100个松散对象,则发生这种情况的概率为32% 搜索4个目录时发生同样情况的概率仅为8%,这有点合理。以下octave script显示至少
m*q
的可能性 如果q
是.git/objects
的{{1}}个n
子目录,则可以找到这些对象 对象总数。
(它使用Cumulative Distribution function (CDF) binomial distribution} {/ p>的binocdf
q = 4;
m = [1 2 8];
n = 0:10:2000;
P = zeros(length(n), length(m));
for k = 1:length(n)
P(k, :) = 1-binocdf(q*m-1, n(k), q/(256-q));
end
plot(n, P);
n \ q 1 4
50 18% 1%
100 32% 8%
200 54% 39%
500 86% 96%
Git's packing heuristics时,该组织还允许git gc
has to occur尽可能快速有效。