Git是一个内容可寻址的文件系统,它具有三种类型的对象:Blob、树和提交。原则上,像ZIP这样的容器文件格式可以被解释为一个类似于Git术语中包含树的单个文件(或链接(的概念。虽然ZIP文件和其他类型的容器在Git中没有任何特殊处理,但这些容器只是作为Blob存储的。
例如,假设我有一个ZIP文件,其中包含一些带有时间戳的文件(时间戳不由Git处理(、空目录,并且在Git存储库中拥有这样的ZIP容器可能被认为是必需的(可能是预编译的JAR文件、经常编辑的OpenOffice文档等(。现在,让我们考虑一下容器正在被稍微修改。从Git的角度来看,这将创建一个完全不同的blob,因此只要容器被反复修改,存储库就会急剧增长。我遇到了一个有趣的干净/污迹过滤器,它可以做类似的事情,但它会在污迹上破坏原始ZIP,覆盖原始ZIP,擦除原始条目时间戳,可能是ZIP注释和其他任何ZIP容器(+据我所知,它使裸存储库很难使用,因为它们不包含仅在签出时创建的"已清理"的ZIP容器(,因此该过滤器对我没有什么兴趣。
我想知道,有没有可能告诉Git将容器存储(可能是ZIP(为Git的一级公民,比如内部的树和水滴?不过,我想它并不支持这种情况。
更新1
我错了,正如下面人们所说,Git中有四种对象类型:我错过了标记对象。然而,我认为它们是建立在提交之上的,就像注释一样(可能(
git中的大多数命令都希望在每个对象的开头找到blob
、tree
、commit
或tag
这四个单词中的一个,因此几乎不可能添加新的对象类型。
这是一个手动实验:
# I created an object with a new type 'foo' :
$ cat .git/objects/70/c52a28ff2b01f46ccc0cdd03c61c569fd6fd54 | pigz -dz; echo
foo10.abcdefghij # the '.' is actually ' '
# all regular git commands start with a "unable to parse header of [object]" :
$ git show 70c52a28ff2b01f46ccc0cdd03c61c569fd6fd54
error: unable to parse 70c52a28ff2b01f46ccc0cdd03c61c569fd6fd54 header
error: unable to parse 70c52a28ff2b01f46ccc0cdd03c61c569fd6fd54 header
fatal: loose object 70c52a28ff2b01f46ccc0cdd03c61c569fd6fd54 (stored in .git/objects/70/c52a28ff2b01f46ccc0cdd03c61c569fd6fd54) is corrupt
$ git fsck
error: unable to parse header of .git/objects/70/c52a28ff2b01f46ccc0cdd03c61c569fd6fd54
error: 70c52a28ff2b01f46ccc0cdd03c61c569fd6fd54: object corrupt or missing: .git/objects/70/c52a28ff2b01f46ccc0cdd03c61c569fd6fd54
Checking object directories: 100% (256/256), done.
# etc ...
一种可能性是编写一个更完整的污点/干净过滤器,它不仅可以存储zip实际内容,还可以存储所有额外的数据(如时间戳、注释…(
这里有一个第一个想法:
如果archive.zip包含dirfile.txt
:
- 创建一个名为
dir
的树 - 将目录头存储在具有已知名称的blob中(例如
dheader
( - 将
file.txt
的报头和内容存储在两个不同的Blob(例如hfile.txt
和_file.txt
(中 - etc用于其他zip元数据
使用不同的前缀应该可以使您在存储所需的每种类型的数据之间有一个清晰的分隔
第二个是:
- 设法将arhive的所有元数据打包在一个blob中
等等。。。
然后,干净的过滤器将有足够的数据来重建相同的存档。
请注意,"重建zip文件"需要干净的过滤器来实现zip存档的所有可能功能(例如:能够以所有已知格式压缩,…(