Hg "history rewrite" (histedit, commit --amend) 之后原始变更集会发生什么情况,如何恢复它们?

What happens to original changesets after an Hg "history rewrite" (histedit, commit --amend), and how can they be recovered?

在 Git 中 - 具有不可变的变更集对象和可变引用 - 我知道原始提交仍然存在,这让我在 'oops' "history rewriting" 时刻后有一种温暖的模糊感觉。

例如,在 "history rewriting" git rebase 之后,原始变更集(cbe7698、09c6268)仍然存在,并添加了新的变更集(08832c0)。我可以很容易地 restore/access 其他变更集,直到它们被修剪。

$ git log --oneline --graph --decorate $(git rev-list -g --all)
* 08832c0 (HEAD -> master) Added bar and quxx to foo.txt
| * cbe7698 Added quxx to foo.txt
| * 09c6268 Added bar to foo.txt
|/
* 895c9bb Added foo.txt

同样,即使是 git commit --amend 也会保留 original/amended 提交 (d58dabc) 并添加新的变更集:

$ git log --oneline --graph --decorate $(git rev-list -g --all)
* d9bb795 (HEAD -> master) Added cats and dogs to pets.txt
| * d58dabc Added cats to pets.txt
|/
* 08832c0 Added pets.txt

但是,"history rewriting" 手术后 Hg 会发生什么变化?

原来的提交不复存在了吗?如果它们仍然存在,如何访问它们 and/or 恢复?

这取决于您是否安装了进化扩展。如果您安装了 evolve 扩展,那么从存储库中实际删除修订的唯一命令是 hg strip;其他命令保留原始提交,但隐藏它们。您可以使用 hg log --hidden(或其他带有 --hidden 标志的命令)查看它们。如果您想永久摆脱它们,可以使用 hg strip --hidden -r 'extinct()' [1].

然而,大多数人只会使用基本的 Mercurial。在这种情况下(对于 hg strip 即使有进化),删除的变更集将作为包存储在 .hg/strip-backup 中。 Mercurial bundle 基本上是一个只读的覆盖存储库;你可以在上面使用 hg log -Rhg tip -Rhg incominghg pull 等。原则上这就是您所需要的,但是输入路径可能有点麻烦。

为方便起见,Facebook 发布了一个针对 Mercurial 的 number of experimental extensions。其中,backups 扩展提供了一个方便的命令 (hg backups),它基本上列出了 .hg/strip-backup 中每个包中的提交(类似于 hg incoming 使用适当模板所做的)和 hg backups --recover 从剥离的提交中提取变更集(类似于 hg pull 所做的)。

[1] 请注意,即便如此,备份也会存储在 .hg/strip-backup 中。如果您想永久地 摆脱它们,您还必须删除该备份。