37.2.7 备份回滚及设置
我在开发Gistore时,最麻烦的就是备份历史的管理。如果不对备份历史进行回滚,必然会导致提交越来越多,备份空间占用越来越大,直至磁盘空间占满。
最早的想法是使用git rebase命令,即将准备丢弃的早期备份历史压缩为一个提交,然后后面的提交再变基到压缩后的提交之上,这样就实现了对历史提交的丢弃。但是这样的操作既费时,又复杂。忽然有一天灵机一动,为什么不用分支来保留回滚的数据?至于备份主线(master分支)则从一个新的提交开始重建。
回滚后master分支如何从一个新提交开始呢?较早的实现是直接重置到一个空提交(gistore/0)上,但是这样会导致接下来的备份非常耗时。最新的实现是使用git hash-object命令,直接对回滚前master分支的最新提交进行改造,创造出一个没有父提交的新提交。
备份回滚的具体实现过程是:
(1)每次备份,都提交在Git库的分支master上。
(2)当Git库的master分支的提交数量达到规定的阈值(默认200)时,则从master分支建立新的分支:gistore/1。如果已有分支gistore/1则建立分支gistore/2,依次类推。
(3)然后master分支重置到一个用git hash-object命令基于当前最新提交建立的一个新提交(没有父提交)。
(4)如果保存备份历史的分支数量达到预先设定的阈值(默认5个分支),分支依次回滚。
用分支gistore/2重置分支gistore/1,用分支gistore/3重置分支gistore/2,依次类推。即保存最早备份历史的分支gistore/1被丢弃。
基于分支master建立分支gistore/5。
(5)当分支重置及回滚发生后,对备份库的远程数据同步不会有什么影响,传输的数据量也仅是新增备份和上一次备份的差异。
虽然备份历史由于master分支的重置被分割为多个独立的片段,但是因为使用了Git提交嫁接[1]的功能,执行gistore log可以看到master分支及其他形如gistore/N分支的所有提交日志。奥秘就在repo.git/info/grafts文件。
[1]第8篇第41章“41.4.h1 提交嫁接”小节。