我想跟踪一个500kb的json文本,它会稍微改变它的内容。我想使用git
,所以我可以在另一台服务器上使用git pull
来下载该文件的最新版本而不会出现问题,该文件可能会在下载过程中发生变化而且我还希望进行版本控制这个文件在过去几个月/几年同时这样。
我想到了创建一个git存储库,我提交了每个文件的更改,但是我注意到,在几天之后,这个存储库的大小会达到很多GB(即使git gc
也是如此,因为文件中的变化太大了)
我可以定期将git截断到特定深度,但这不是我需要的。我需要这些信息,文件看起来像一周前,一个月前,一年前。虽然我不需要那么多的提交,但过去的时间越长。
使用git和一些bash魔法甚至可以实现这一点吗?我可以删除并重新创建存储库并在该git中使用--amend
或者你会建议另一种解决方案吗?
答案 0 :(得分:1)
至少有一种方法可以做到这一点;我将在下面概述一种方法。首先要考虑一些事情:
根据发生的更改的性质,您可能希望查看数据库的频繁打包是否有帮助; git非常擅长避免浪费空间(至少对于文本文件)。
当然,您描述的提交负载 - 每天1440次提交,给予还是采取? - 历史将趋于增长。尽管如此,除非这些变化在每次提交时都是戏剧性的,否则它似乎可以比“几天内的许多GB”更好;也许你达到妥协归档策略变得切实可行的水平。
关于“我需要保留的所有数据”是否大于“我需要定期访问的所有数据”,总是值得思考;因为那时你可以考虑是否应该在归档回购中保留一些数据,可能是在某种形式的备份媒体上,而不是作为现场回购的一部分。
而且,正如你在问题中提到的那样,你可能想要考虑git是否是最适合这项工作的工具。您描述的用法不会使用git的大部分功能;它也没有运用真正让git出类拔萃的功能。相反,其他工具可能会更容易逐渐淡化历史。
但是,所有这些都说,您仍然可能决定以“每分钟”数据开始,然后最终将其降至“每小时”,并且可能仍然会降低到*每一周“。
(我不鼓励定义太多多个级别的粒度;最大的“砰然响亮”将会丢弃每小时一次的快照。小时 - >天将是临界的,白天 - >周可能会浪费。如果你每周都要下去,那肯定是足够稀疏......)
因此,当某些数据“老化”时,该怎么办?我建议你可以使用一些组合的变基(和/或相关操作),深度限制和替换(取决于你的需要)。根据您如何组合这些,您可以保持无缝历史的错觉,而无需更改任何“当前”提交的SHA ID。 (使用更复杂的技术,您甚至可以安排从不更改SHA ID;但这显然更难,并且会在一定程度上减少空间节省。)
因此,在下图中,有一个根提交标识为“O”。后续提交(细微更改)由字母和数字标识。该字母表示创建提交的日期,数字按顺序标记分钟。
您可以为最终使用的每个历史记录粒度创建初始提交并在其上放置分支。 (随着每分钟的变化累积,它们将继续master
。)
O <--(master)(hourly)(weekly)
几天后你就
了O <-(hourly)(weekly)
\
A1 - A2 - A3 - ... - A1439 - A1440 - B1 - B2 - ... - B1439 - B1440 - C1 <--(master)
也许你已经决定在午夜时分,可以丢弃任何24小时的小时快照。
因此,当C
天开始时,A
快照的时间超过24小时,应缩短为每小时快照。首先,我们必须创建每小时快照
git checkout hourly
git merge --squash A60
git commit -m 'Day A 1-60'
git merge --squash A120
git commit -m 'Day A 61-120'
...
这会给你
O <-(weekly)
|\
| A60' - A120' - ... - A1380' - A1440' <-(hourly)
\
A1 - A2 - A3 - ... - A1439 - A1440 - B1 - B2 - ... - B1439 - B1440 - C1 <--(master)
这里A1440'
是A1440
的重写,但是有不同的父母(这样它的直接父母是“一小时前”而不是“一分钟前”)。
接下来,为了使历史无缝,您可以B1
将A1440'
标识为其父级。如果您不关心更改每个提交的SHA ID(包括当前提交),则可以使用rebase
git rebase --onto A1440' A1440 master
或者在这种情况下(由于TREE
和A1440
的{{1}}相同),它等同于重新父A1440'
- 请参阅{{ 1}} docs了解该方法的详细信息。无论哪种方式,你最终都会
B1
请注意,即使git filter-branch
和O <-(weekly)
|\
| A60' - A120' - ... - A1380' - A1440' <-(hourly)
| \
| B1' - B2' - ... - B1439' - B1440' - C1' <-(master)
\
A1 - A2 - A3 - ... - A1439 - A1440 - B1 - B2 - ... - B1439 - B1440 - C1
提交中的更改粒度未更改,这些仍然是“重写”提交(因此B
表示法);事实上,原始提交尚未被物理删除。但是,它们无法访问,因此它们最终会被C
清除;如果这是一个问题,您可以通过丢弃超过24小时的reflog然后手动运行'
来加快这一点。
或者,如果您要为gc
和gc
提交保留SHA ID,则可以使用B
。
C
但是这有许多缺点。有一些已知的怪癖有替代品。同样在这种情况下,原始提交不可达(即使默认情况下不显示);你必须浅薄git replace
分支才能摆脱它们。浅析分支的最简单方法是克隆repo,但是你必须通过额外的环来传播替换refs。因此,如果您不希望git replace A1440 A1440'
引用“意识到”它以异常方式移动,而不是那么简单,那么这是一个选项。