如何将文件保存为git树而不是blob?

时间:2017-09-14 09:57:50

标签: git tree githooks git-filter

由于许多文件格式都具有树状结构(例如XML,tar,甚至MP3,如果你考虑将标签和框架拆分为叶子),我想知道是否有任何方法让git将它们存储为树对象而不是blob,利用结构,例如用于区分和合并。

到目前为止,我考虑使用挂钩或涂抹/清洁过滤器,但两者都有我想避免的缺点:

  • 使用只重写blob(即文件内容)的clean-filter,我可以并行创建并git add一棵树,并用涂抹过滤器的足够信息替换blob,以重新创建原始文件在结帐时。但是,这会使git status声明"目录"缺少内部表示的树,这是一个占位符文件,可能会阻止添加同名树
  • 使用post-commit钩子会搞砸git diff等很多

有没有明智的方法来实现这一目标?或者我应该坚持使用blob并修改merge / diff驱动程序?

2 个答案:

答案 0 :(得分:1)

Git本身试图成为内容形式不可知论者。也就是说,对于第一个近似,它只关心原始数据 - 甚至不是文本与二进制,只是"这里有一些数据作为文件集合;请存储它。" (Linus'原始视觉没有,我认为,包括CR / LF转换,只要它从未开启,它就不会损坏二进制数据。)

这种不可知论很快就会崩溃。将一个提交与另一个提交进行比较首先是通过比较文件,但超出简单的提交A中的路径名p / a / t / h必须与提交B中的路径名p / a / t / h相同的文件" - 当两个路径都存在且命名相同的内容时,它很有用 - 我们很快发现我们需要比较相似但不相同的文件,并希望在某种结构基础上这样做:line例如,或面向文字的diff。而且,为了处理重命名问题,如果p/a/t/h变为p/t/h,反之亦然,我们可能希望将这些文件相互匹配,即使它们仅相似,例如90%相似。

(其他VCS记录一些其他类型的文件标识,而不仅仅是路径名,每次提交,通过记录目录操作或通过为文件分配唯一的内部ID .Git没有,所以它必须依赖在这个相似性检测系统上.Git的相似性检测器是特殊的:它不是面向行的,因此它可以处理二进制文件,但它确实检测行边界以消除\ r \ n vs \ n其相似性检测器的变化。)

无论如何,你肯定可以采取Git并修改它以添加新的对象类型,如树木和#34;但有不同的味道。那会让你分开这些结构化文件。它的工作效果似乎基本上是一个研究课题。只是将它们插入到作为树中显然不能很好地工作,但是:你永远不会知道某个树实例是否是一个"派生的树"或者是真正的树"。为了避免更改Git的某些核心代码,您可以在Git读取和写入其索引的位置插入您的真实与派生/合成树转换,并编码" real" vs"合成"进入"文件名"。

如果存储在每个合成子树中的原始数据本身是二进制的,那么您将遇到通常的难题,即差异无法使用。包文件存储格式(基于xdelta)不是面向行的,但使用路径名的包启发式可能执行得不是很好,所以您可能也想修改它们。从xdelta获得的压缩量取决于输入数据中的Shannon entropy:二进制vs文本在这里实际上不是问题,除非典型的文本输入具有相当低的熵;二进制输入往往不太可预测。

答案 1 :(得分:-1)

如果您尝试在Git中添加任何二进制文件(如XML,tar,MP3),它们将被区别对待。

Git适用于非二进制文件。如果您要定期包含二进制文件,请考虑使用Git LFS等二进制存储解决方案。