Mercurial:如何修改最后一次提交?

时间:2011-11-18 13:04:02

标签: mercurial commit amend mercurial-commit

我在Mercurial中寻找git commit --amend的反对部分,即修改我的工作副本所链接的提交的方法。我只对最后一次提交感兴趣,而不是先前提交的任意提交。

此修订程序的要求是:

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

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

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

更新(1):

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

更新(2):

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

8 个答案:

答案 0 :(得分:279)

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

来自command line reference

  

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

     

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

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

答案 1 :(得分:51)

您可以使用3个选项来编辑Mercurial中的提交:

  1. hg strip --keep --rev -1撤消最后一(1)次提交,以便您可以再次执行此操作(有关详情,请参阅this answer)。

  2. 使用Mercurial附带的MQ extension

  3. 即使它未随Mercurial一起提供,Histedit扩展名也值得一提

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

    简而言之,编辑历史非常困难且气馁。如果你已经推动了你的改变,除了你完全掌控所有其他克隆外,你几乎无能为力。

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

答案 2 :(得分:37)

hg commit --amend的等效GUI:

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

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

enter image description here

          ||
          ||
          \/

enter image description here

警告经纪人

  

仅在mercurial版本至少时才会启用此额外选项   2.2.0,如果当前版本不公开,则不是补丁而且没有补丁   儿童。 [...]

     

单击该按钮将调用   'commit --amend''修改'修订版。

有关此on the THG dev channel

的详细信息

答案 3 :(得分:7)

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

<强>假设:

  • 您已经提交了一个(!)更改集但尚未推送它
  • 您要修改此更改集(例如,添加,删除或更改文件和/或提交消息)

<强>解决方案:

  • 使用hg rollback撤消上次提交
  • 再次提交新的更改

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

答案 4 :(得分:7)

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

  • 添加到.hgrc:

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

    hg qimport -r0:tip
    hg qpop -a
    

    当然你不需要从修订版零开始或弹出所有补丁,最后只需要一个pop(hg qpop)就足够了(见下文)。

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

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

如果您不想 取回补丁的所有,您可以使用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

当然,这个程序非常气馁且风险很大在您执行此操作之前对所有内容进行备份

作为旁注,我在私人存储库中完成了数十万次。

答案 5 :(得分:1)

Mercurial的最新版本包括提供evolve命令的hg amend扩展名。这允许修改提交而不会丢失版本控制中的预修改历史记录。

  

hg修改[OPTION] ... [FILE] ...

     

别名:刷新

     

将变更集与更新相结合,并将其替换为新的

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).

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

答案 6 :(得分:0)

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

如果您像我一样,并且只希望修改前一个提交消息(修正错字等)而不添加任何文件,则可以使用

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

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

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

答案 7 :(得分:0)

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

hg uncommit [file/directory]

当您要保留当前提交并从提交中取消选择某些文件时(这对files/directories尤其有用)特别有用。