219

我正在寻找git commit --amendMercurial 的对应部分,即修改我的工作副本链接到的提交的方法。我只对最后一次提交感兴趣,而不是任意的早期提交。

此修订程序的要求是:

  • 如果可能,它不应该需要任何扩展。它不能要求非默认扩展,即不附带官方 Mercurial 安装的扩展。

  • 如果要修改的提交是我当前分支的一个负责人,则不应创建新负责人。如果提交不是 head,则可能会创建一个新的 head。

  • 该过程应该是安全的,如果由于某种原因修改失败,我希望恢复与修改前相同的工作副本和存储库状态。换句话说,如果修改本身可能失败,则应该有一个故障安全程序来恢复工作副本和存储库状态。我指的是修正程序性质的“故障”(例如冲突),而不是与文件系统相关的问题(例如访问限制,无法锁定文件以进行写入,... )

更新(1):

  • 该过程必须是可自动化的,因此它可以由 GUI 客户端执行,而无需任何用户交互。

更新(2):

  • 不得触摸工作目录中的文件(某些修改的文件可能存在文件系统锁定)。这尤其意味着,一种可能的方法可能在任何时候都不需要干净的工作目录。
4

8 回答 8

296

随着Mercurial 2.2的发布,您可以使用--amend选项 withhg commit将最后一次提交更新为当前工作目录

从命令行参考

--amend 标志可用于使用新提交修改工作目录的父级,该提交包含父级中的更改,以及当前由 hg status 报告的更改(如果有的话)。旧的提交存储在 .hg/strip-backup 的备份包中(参见 hg help bundle 和 hg help unbundle 了解如何恢复它)。

除非另有说明,否则消息、用户和日期取自修改后的提交。当命令行中未指定消息时,编辑器将打开修改提交的消息。

很棒的是,这种机制是“安全的”,因为它依赖于相对较新的“阶段”功能来防止更新会改变已经在本地存储库之外提供的历史记录。

于 2012-05-02T18:46:37.820 回答
55

您有 3 个选项可以在 Mercurial 中编辑提交:

  1. hg strip --keep --rev -1撤消最后 (1) 次提交,以便您可以再次执行此操作(有关更多信息,请参阅此答案)。

  2. 使用Mercurial 附带的MQ 扩展

  3. 即使没有随 Mercurial 提供,Histedit扩展也值得一提

您还可以查看 Mercurial wiki 的Editing History页面。

简而言之,编辑历史真的很辛苦,也很气馁。如果您已经推送了更改,那么您几乎无能为力,除非您可以完全控制所有其他克隆。

我不太熟悉这个git commit --amend命令,但是 AFAIK,Histedit 似乎是最接近的方法,但遗憾的是它没有随 Mercurial 一起提供。MQ 使用起来确实很复杂,但您几乎可以用它做任何事情。

于 2011-11-18T13:34:04.903 回答
39

GUI等效于hg commit --amend

这也适用于 TortoiseHG 的 GUI(我使用的是 v2.5):

切换到“提交”视图,或者在工作台视图中,选择“工作目录”条目。“提交”按钮有一个名为“修改当前版本”的选项(单击按钮的下拉箭头找到它)。

在此处输入图像描述

          ||
          ||
          \/

在此处输入图像描述

警告购买者

仅当 mercurial 版本至少为 2.2.0 并且当前版本不是公开的、不是补丁且没有子版本时,才会启用此额外选项。[...]

单击该按钮将调用“commit --amend”来“修改”修订。

在 THG 开发者频道上了解更多信息

于 2013-01-04T11:04:08.223 回答
7

我正在调整 krtek 所写的内容。更具体地说,解决方案1:

假设:

  • 你已经提交了一个(!)变更集,但还没有推送它
  • 你想修改这个变更集(例如添加、删除或更改文件和/或提交消息)

解决方案:

  • 用于hg rollback撤消最后一次提交
  • 再次提交新的更改

回滚确实撤消了最后一个操作。它的工作方式非常简单:HG 中的正常操作只会追加到文件;这包括提交。Mercurial 跟踪最后一个事务的文件长度,因此可以通过将文件截断回原来的长度来完全撤消一个步骤。

于 2011-11-18T13:47:33.280 回答
7

假设您尚未传播您的更改,您可以执行以下操作。

  • 添加到您的 .hgrc:

    [extensions]
    mq =
    
  • 在您的存储库中:

    hg qimport -r0:tip
    hg qpop -a
    

    当然,您不必从零版本开始或弹出所有补丁,因为最后一个 pop ( hg qpop) 就足够了(见下文)。

  • 删除.hg/patches/series文件中的最后一个条目,或您不喜欢的补丁。重新排序也是可能的。

  • hg qpush -a; hg qfinish -a
  • 删除.diff仍在 .hg/patches 中的文件(未应用的补丁)(在您的情况下应该是一个)。

如果您不想收回所有补丁,您可以使用hg qimport -r0:tip(或类似方法)对其进行编辑,然后编辑内容并使用将hg qrefresh更改合并到堆栈中最顶层的补丁中。阅读hg help qrefresh

通过编辑.hg/patches/series,您甚至可以删除多个补丁,或重新排序一些补丁。如果您的最新版本是 99,您可以只使用hg qimport -r98:tip; hg qpop; [edit series file]; hg qpush -a; hg qfinish -a.

当然,这个过程是非常不鼓励和冒险的。在执行此操作之前备份所有内容!

作为旁注,我已经在私有存储库上做了无数次。

于 2011-11-18T14:04:37.737 回答
2

Mercurial 的最新版本包括evolve提供hg amend命令的扩展。这允许在不丢失版本控制中的预修改历史的情况下修改提交。

hg 修改 [选项]... [文件]...

别名:刷新

将变更集与更新组合并用新的替换它

Commits a new changeset incorporating both the changes to the given files
and all the changes from the current parent changeset into the repository.

See 'hg commit' for details about committing changes.

If you don't specify -m, the parent's message will be reused.

Behind the scenes, Mercurial first commits the update as a regular child
of the current parent. Then it creates a new commit on the parent's
parents with the updated contents. Then it changes the working copy parent
to this new combined changeset. Finally, the old changeset and its update
are hidden from 'hg log' (unless you use --hidden with log).

有关扩展的完整描述,请参阅https://www.mercurial-scm.org/doc/evolution/user-guide.html#example-3-amend-a-changeset-with-evolve 。evolve

于 2018-03-06T12:12:42.450 回答
2

可能无法解决原始问题中的所有问题,但由于这似乎是关于 mercurial 如何修改先前提交的事实上的帖子,我将添加我价值 2 美分的信息。

如果您像我一样,只想修改之前的提交消息(修复错字等)而不添加任何文件,这将起作用

hg commit -X 'glob:**' --amend

没有任何包含或排除模式hg commit将默认包含工作目录中的所有文件。应用模式-X 'glob:**'将排除所有可能的文件,只允许修改提交消息。

git commit --amend在功能上,它与索引/阶段中没有文件时相同。

于 2019-07-03T18:02:50.780 回答
0

另一种解决方案是使用该uncommit命令从当前提交中排除特定文件。

hg uncommit [file/directory]

当您想要保留当前提交并从提交中取消选择某些文件时,这非常有用(特别有助于files/directories已被删除)。

于 2020-01-07T13:16:28.757 回答