如何在Hg中删除一些变更集?

7
嘿,我想撤销Hg中的一些变更集,但是我很难这样做。
我不小心提交了一些更改,所以我想撤消它。尝试了一下后,我能够使用hg backout,但它创建了一个新的提交。现在,我想让我的存储库回到初始状态(没有最后2个提交,并且具有工作目录中的更改)。显然没有办法做到这一点(类似于git reset --soft)。有吗?
我尝试的另一件事是摆脱最新的提交(撤消原始提交的那个)。这将类似于git reset --hard,但是再次,没有办法这样做。我可以hg update -C,但那更像是git checkout,因为提交仍然存在。
此外,hg update -C -r X将我恢复到修订版本X,但是当我检查hg log时,我无法知道我现在在哪个修订版本中。唯一的方法是检查我的bash历史记录,这样对吗?必须有一种方法来知道这一点。
无论如何,我一直在尝试解决这个问题,但是找不到任何解决方法。我找到的比较git和hg命令的参考资料不准确,因为这些命令的行为并不完全相同。
我想知道的只是在Hg中git reset --hardgit reset --soft的真正等效性是什么...
谢谢。

这不是对你的主要问题的答案,但是要查看您所在的修订版本,请执行 hg summary。如果您只想查看修订版本,请使用安静标志:hg summary -q - Cody Piersall
5个回答

9
Mercurial故意不让这个过程变得容易。Mercurial的思路是提交的代码应该继续存在——记录未成功的内容几乎与记录成功的内容同样重要。最好提交你的工作的否定(这就是backout所做的),仍然保留记录,而不是实际丢弃它。
但如果你真的不能让这个更改继续存在(好的原因:它包含了一个你无法更改的密码,坏的原因:它只是没成功),你有几个选择:
- strip: 我不喜欢strip,它会修改仓库并不会将东西放回工作目录。默认情况下禁用strip是有原因的。 - clone: 只需执行hg clone -r LASTCHANGESETYOULIKE oldrepo newrepo,现在newrepo包含了LASTCHANGESETYOULIKE以及之前的所有内容。归档oldrepo并将newrepo重命名为oldrepo即可。 - rollback: 这是mercurial世界中的一级撤销。它会在你提交后立即撤销你的提交,但如果你已经进行了任何其他的pulls或commits,它就无效了。

很棒。非常感谢你的回答。它澄清了很多事情。只有一个最后的问题:是否有任何命令可以将提交撤消到工作目录中?(例如git reset --soft)--原因是为了更轻松地使用我喜欢的差异软件来检查该提交的内容。 - Gaisorama
hg rollback 就像 git reset --soft HEAD^ - wRAR
是的,就像wRAR所说的那样,rollback 是一级撤销操作,它可以撤销一个提交(前提是你在此之后没有进行过拉取操作)。不过,你可以尝试使用 extdiff 扩展,它可以让你轻松地比较最近的提交和工作目录,而无需为了这个目的而进行提交操作。 - Ry4an Brase
@wRAR,“hg rollback”不像“git reset --soft HEAD^”。如果“hg rollback”出了问题,你无法撤消它。 - Mihai
@JohnGietzen,我猜你当前喜欢的编程语言不会直接暴露对任意内存地址的写入,而不是因为它们没有用,而是因为它们“非常锋利”。甚至可能根本不可能实现。Mercurial将“不变性”作为设计决策,不是因为他们不信任你,而是因为当你接受不变性时,其他一些非常困难的事情变得更容易了。问问lisp/ml/haskell/clojure的人吧。他们避免可变性不是因为它“锋利”。另请参见:http://mercurial.selenic.com/wiki/Phases。我使用git和hg,它们都很好。 - Ry4an Brase

7

以下是如何执行git reset --soft的步骤。假设您有以下这样一个图形:

... --- [A] --- [B] --- [X] --- [-X]

其中X是错误提交,-X是你撤销的提交。现在你想要删除X-X,同时保留工作副本与提交X时相同的状态。你可以执行以下操作:

$ hg update B
$ hg revert --all --rev X # working copy now looks just like in X
$ hg strip --force X      # get rid of X and -X

如果你想的话,你可以在Mercurial 1.7中为此创建一个别名:
[alias]
softreset = !hg update 'p1($1)' &&
             hg revert --all --rev $1 &&
             hg strip --force $1

在使用hg revert后,脏的工作副本使得必须使用hg strip --force。您可以使用以下命令:

$ hg softreset 10

这将删除10及其所有后代,同时保留10中的更改内容。当然,您可以进一步实现hg reset命令:

[alias]
reset = !test "$1" = "--hard" && hg strip $2 || hg softreset $2

这些别名的最大问题在于错误处理不佳。用Python编写的扩展性更强,更易维护 - 也许你可以制作这样一个“重置”扩展并在Bitbucket上发布 :)

3

请查看来自 mq 扩展的 hg strip


很酷,hg strip可以完成reset --hard的工作。 - Gaisorama
无法像git reset --soft那样使其工作...(将更改保留在工作目录中) - Gaisorama

1

你已经得到了一些好的答案,但还有一些额外的注意事项:

  • 如果你有未提交的本地更改,shelve会为你设置它们以便稍后检索
  • 如果你的变更集已经被推送到另一个存储库,那么除了编辑两个存储库之外,撤销是你唯一的选择
  • 撤销允许你创建一个新的变更集,它是原始变更集的反向,消除不需要的更改而不改变存储库的历史记录
  • 如果你还没有将变更推送到远程存储库,回滚通常是最好的选择,因为它会消除变更集,同时保留你的工作副本
  • Strip可以摆脱整个变更分支,但像回滚一样,只有在你没有将变更推送到其他地方时才会保持消失
  • 对于克隆到先前版本的存储库,其他工具更容易使用,同样适用于其他工具

0

关于git的事情不确定,但如果您还没有推送,可以使用hg rollback。如果您已经推送了,那么您真的无法做什么好的。

至于当前版本,请参见hg id


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