在Git Repo中逐步保存Clojure数据结构

3

注意:

这里标记了Clojure和Git,因为我很乐意在软件的Clojure和Git两侧进行重新设计以使事情顺利。

问题:

我有一堆Clojure数据结构。当写入磁盘(使用pr)时,它们平均每个文件大约100 KB。我有大约1000个这样的文件。这些文件是“结构化”的文档-将它们视为等同于SVG。

现在,我正在对这些文件进行许多小的更新(添加/删除节点,在节点上更改属性)。 (然后我会将这些文件写出(pr ...)。

最后,我将所有这些文件存储在我的git repo中。

问题:

我想知道是否有一种有效的方式来存储这些文件(因为不同的写入只有小的修改)-即如果我在内存中有单个文档的两个副本,则为1MB + epsilon,而不是2MB(因为两个文档只有轻微差异,并共享大部分结构。)

我想以某种方式利用这个事实,并在存储到git时利用这种相似性。

可能考虑的解决方案:

1)在Clojure方面,不要写出整个文件,而是只写出与前一个文件的“差异[包括assoc,dissoc]”。<--这需要大量工程。

2)在FS方面,不要存储单个文件,而是将整个目录放入bzip中,然后将其提交为单个*.bz2(因此,相似的文件将具有相似的块)。缺点是在git中存储*.bz2文件似乎不是一个好主意。

2个回答

3

您考虑过使用Datomic而不是Git吗?

您正在做的事情听起来非常适合使用Datomic,它本质上是一个“事实图”数据库,类似于Clojure的风格 - 这几乎正是您的结构化数据所看起来的样子。

Datomic以与Clojure的不可变数据结构非常相似的方式存储数据,即它使用结构共享来确保小的更改仅需要少量的额外空间。它还以类似于git的方式保留了整个历史记录 - 甚至有一个工具可以在Datomic中模拟git存储库(codeq)。


1

这是一个有趣的问题。让我们看看我们能做什么。

GIT在其数据库中保存你添加到存储库中的文件的完整副本。然而,当你运行git gc来优化你的本地存储库时,Git会将松散的对象打包成包文件。相似的文件使用增量压缩存储在包文件中。引用Pro Git:

当Git打包对象时,它会寻找名称和大小类似的文件,并存储从文件的一版本到下一版本的增量差异。

因此,Git中类似文件的存储被优化,空间使用得到减少。

让我们从内部转向用户界面部分。从用户的角度来看,GIT基于差异。当你浏览提交、合并补丁和审查更改时,你主要处理差异。差异是基于行的。因此,单行的最小变化会导致生成的差异中旧版本和新版本的整个行都被存储。我们如何使你描述的文件之间的差异更易于阅读?缩短行长度即可。我看到两种简单的实现方式。

首先,不要保存Clojure数据结构,而是将它们转换为YAML。以YAML格式存储数据的文件具有相对较短的行,这解决了问题。clj-yaml应该很有用。

如果您坚持将数据存储为s表达式,则第二个想法是将生成的文件中的所有空格替换为换行符。如果可读性很重要,您可以在之后进行缩进。在应用简单的正则表达式将每个空格替换为\n之前,请检查是否有包含空格的字符串。


有趣的是,我知道Git将事物存储为DAG,但我不知道Git将不同版本存储为差异(尽管回想起来很明显)。这非常聪明。因此,理想情况是将Clojure结构中的更改映射到行中的更改,然后由差异捕获。 - user1647794
@user1647794,没错。这样可以使差异最小化,从而减少每个提交的大小。 - Jan
事实上,Git并不基于差异。 - Laurent Petit
@LaurentPetit,感谢您的评论。我已经修改了答案并澄清了我所做的过度简化。您认为这个版本准确吗? - Jan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接