问题描述
|
是否可以备份具有许多Mercurial存储库的文件系统(例如,在文件系统上具有rsync)并且备份状态不一致?
信息库由ssh提供服务,并满足以下请求集:{push,pull,in,out,clone}。它没有直接应用“ hg commit”(具有已知的竞争条件)。
解决方法
马克·德拉戈(Mark Drago)是正确的,因为Mercurial会谨慎地编写自己的文件以保持完整性。但是,这只是相对于其他Mercurial客户而言的完整性。 Mercurial中的锁定设计允许一个Mercurial进程通过按以下顺序写入文件来创建新提交:
filelogs(保存给定文件的所有修订版的压缩增量)
清单(具有指向与给定变更集关联的文件日志的指针)
changelog(具有元数据和指向变更集清单的指针)
而其他Mercurial进程将按此顺序读取文件
变更日志
表现
文件日志
因此,读者将看不到对新文件日志数据的引用,因为更改日志最后是在原子操作(重命名,POSIX必须是原子的)中更新的。
备份程序将不知道读取Mercurial文件的正确顺序,因此它可能会在Mercurial更新文件之前读取文件日志,然后在更新文件之后读取清单:
rsync
读.hg/store/data/foo.i
hg
写.hg/store/data/foo.i
hg
写.hg/store/00manifest.i
hg
写.hg/store/00changelog.i
rsync
读.hg/store/00manifest.i
rsync
读.hg/store/00changelog.i
结果是备份带有更改日志,该更改日志指向清单,该清单指向不存在的文件日志修订---损坏的存储库。在这样的存储库上运行“ 12”会检测到这种情况:
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
foo@1: f57bae649f6e in manifests not found
1 files,2 changesets,1 total revisions
1 integrity errors encountered!
(first damaged changeset appears to be 1)
这告诉您修订版1的清单引用文件foo
的修订版f57bae649f6e
,但找不到。可以通过制作排除错误修订版本1的克隆来修复这种情况:
$ hg clone -r 0 . ../repo-fixed
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
updating to branch default
1 files updated,0 files merged,0 files removed,0 files unresolved
$ cd ../repo-fixed
$ hg verify
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
1 files,1 changesets,1 total revisions
因此,总而言之,如果您使用常规的备份程序来备份Mercurial存储库,那还不错。请注意,从备份还原损坏的存储库后,可能必须对其进行修复。您丢失的变更集很可能仍将保留在开发人员的计算机上,修复恢复的存储库后,他可以再次推送它。 Mercurial Wiki具有有关修复存储库损坏的更多信息。
备份存储库的完全安全的方法当然是使用ѭ17,但是将其与常规备份策略集成可能并不实际。
, 为什么只用17英镑就不“备份”它? ;-)
, 简短的答案是:您可以复制(cp,rsync等)Mercurial存储库而不会出现问题。
更长的答案是:https://www.mercurial-scm.org/wiki/Presentations?action=AttachFile&do=get&target=ols-mercurial-paper.pdf(特别是第5节,副标题“ Committing Changes \”) 。
Mercurial按顺序写出更改,以使其他任何过程都可以随时安全地读取Mercurial存储库。如果在对存储库进行更改的同时将存储库复制到其他位置,则会获得一些新数据,但是Mercurial很聪明,可以忽略部分写入的提交。当您使用制作为商品库的副本时,无论是否看到新提交,都不会出现任何损坏。