在Mercurial中,是否有类似于"bzr uncommit"的功能?

12

Bazaar有一个很棒的uncommit命令,它可以简单地撤消上一次提交。Mercurial中是否有相应的功能?

编辑:Bazaar的uncommit命令不会修改文件,而是删除上一次提交及其关联数据(例如,当您发现提交消息中有错别字或漏掉了某个文件时非常有用)。

例如:

$ bzr ci -m "Fixed a proooblem" <-- problem is misspelt
$ bzr uncommit
...
$ bzr ci -m "Fixed a problem" <-- Exactly as if the first commit was correct.
5个回答

23

你想使用hg rollback命令,但如果你正在使用Mercurial 2.2或更高版本,请参阅下文。

rollback命令将从您的存储库中删除最后一个事务(transaction)。提交(commit)是一个事务,所以您可以将其用作

% hg commit -m 'My elaburate bugfix.' foo.c foo.h
% hg rollback
% hg commit -m 'My elaborate bugfix.' foo.c foo.h

回滚后,文件将再次被视为已修改,这意味着第二次提交将存储与第一次相同的更改,但使用更好的提交消息。

注意:hg rollback比简单的“撤消”功能更强大,如果不小心使用,您可以使用它来丢弃工作。要丢弃提交,请执行以下操作:

$ hg commit -m 'My big and very difficult bugfix'
$ hg pull --update
$ hg rollback

如果你更新了工作副本到其他版本,那么你现在已经丢失了最后一次提交并且那个提交中的更改已经消失了。所以只有当你确定hg commit确实是最后一个作用于工作副本的命令时,才应该使用hg rollback来撤销一个提交。

此外,如果你没有在命令行上给出提交消息,那么你不能只通过按两次向上箭头来重做提交。然而,Mercurial 1.5及更高版本会将你最后的提交消息保存在.hg/last-message.txt文件中,这样你可以在撤销提交后再次找到它。

Mercurial 2.2新增了一个新的--amend标志,用于hg commit。它让你在最后一次提交中添加新的更改。它将hg status列出的更改内容合并到父提交中,就像你进行了回滚并再次提交一样。


8
也许可以使用hg backout tip命令?我建议查看http://hgbook.red-bean.com/read/finding-and-fixing-mistakes.html,了解有关hg backout的所有详细信息,包括它与hg revert的区别以及许多相关主题。但是,如果我理解uncommit的功能,它似乎与hg backout tip完全等效。
编辑:在您的评论中,您现在澄清了您想要“删除历史记录”-这很困难(除非您非常快速地进行操作,也许;-)……根据红豆书再次说明:
由于Mercurial将历史记录视为累积的-每个更改都建立在之前的所有更改之上-因此您通常不能使灾难性的更改消失。唯一的例外是当您刚刚提交了更改,并且它还没有被推送或拉入另一个存储库时。那时候,您可以安全地使用hg rollback命令。
因此,如果您只想尝试“使其消失”(并且很幸运它还没有被推送或拉到其他地方),那么hg rollback可能是更好的方法!

接近了,但还不够。 bzr revert会保留所有文件,准备重新提交。 - David Wolever
1
无论如何,“hg rollback”似乎更像是你想要的——它会回滚最新的_事务_(提交或拉取),但是,根据红豆书的说法,“你只能回滚一次”,“一旦你推送了,它就没用了”。 - Alex Martelli
啊,是的 - 我刚刚在阅读关于回滚的内容,所以我想回到这里看看是否有更多的评论。 回滚几乎是我想要的...但它不会为我放回文件(即,需要还原才能将文件放回提交之前的位置)...但我想我不会再抱怨了 :) 感谢您的帮助,Alex! - David Wolever

0

还有"mq"扩展中的"hg strip"命令。它几乎等同于"bzr uncommit"。但要注意,如果你之前将错误提交推送到另一个存储库,则会在从该存储库进行最近一次拉取时重新创建该提交。


抱歉,这是不正确的——hg strip将从存储库中删除变更集,而bzr uncommit将使存储库和工作树回到提交之前的状态。 - David Wolever
这就是为什么我使用“几乎”这个词的原因——唯一的区别似乎只在于工作目录的状态。我认为值得一提的是,这是“bzr uncommit”的唯一Mercurial等效命令(不幸的是,这是一个不明显的命令,很难找到),能够删除多个提交之后的变更集。根据Bazaar文档,bzr uncommit可以做到这一点。如果您知道另一个可以删除多个变更集的历史操作Mercurial命令(例如“bzr uncommit -r 1”),请告诉我。我很乐意了解它。 - m--s

0

"hg revert" 不是可以做到这个吗?


它将还原文件,但我希望整个提交(包括消息)从历史记录中删除。 - David Wolever
或者可能是hg help revert没有显示给我什么东西...? - David Wolever
2
“hg revert”不会更改历史记录。相反,“hg revert”更改的是工作副本——您可以使用它将未提交的更改还原回某个早期版本(通常是工作副本父版本)。如果要重做提交,您不能使用“hg revert”,我建议使用“hg rollback”。 - Martin Geisler

0

从评论中看来,您想要一种简单的方法来消除提交记录,而不撤销文件的更改。在Mercurial中,没有自动化的方法可以做到这一点。hg revert是最接近您要求的。

但是,您可以通过几个手动步骤来实现这一点。当您调用hg revert时,它的默认行为是将您要还原的变更集中的文件重命名为filename.ext.orig,其中ext是文件的原始扩展名。然后还原版本将采用原始文件名。因此,您可以运行hg revert,删除具有原始名称的文件,并从备份文件的名称中删除.orig。然后使用更正的日志消息重新提交。只是不要在除了tip之外的任何修订版上这样做,因为您可能会得到很多更改的文件,并忘记哪些文件属于哪个变更集。

如果您已经将您的变更集推送到远程存储库中,我也不建议您这样做。只有在所有内容仍然只是本地的情况下才这样做。

如果您需要进一步的解释,请告诉我。我曾经不得不这样做,所以我熟悉这个过程。


谢谢您的评论,但我认为hg rollback是我要找的。 - David Wolever
从hg命令行帮助中rollback的说明中可以看到,“它还将恢复最后一次事务时的dirstate。”这不是你想要避免的吗? - Marc W
@Marc:不,他也想要dirstate。这是跟踪已添加文件的东西。所以,“hg add foo.c; hg commit; hg rollback”将像“hg status”一样保留foo.c的添加状态。 - Martin Geisler
顺便说一句,我同意谈论“dirstate”是很差的风格,因为用户不应该意识到这个术语。 - Martin Geisler

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