我有一个存储库,正在使用mq补丁队列处理未完成的更改。修补程序队列也处于版本控制之下。
假设我有两个补丁p1和p2(按顺序应用(。现在我在p1上做了一个更改:
hg qnew p1
...
hg qnew p2
...
hg qref
hg com --mq -m"(Commit before reject)"
hg qpop p1
{make change}
hg qref
hg qpush -a
乙方未提出申请。
现在的标准方法是手动应用被拒绝的大块。我想要使用类似MqMergePatch的东西,这很好,并使用mercurial——但它是基于不推荐使用的功能:
hg qsave // deprecated: use "hg rebase" instead
我的问题是:如何使用hg-rebase?
编辑
看过存储库的日志后,我一点也不喜欢MqMergePatch对它所做的一切。我使用补丁的主要目标是清理存储库的历史记录,而不是散布无用的细节。
我认为使用hg rebase
的建议具有误导性。MqMergePatch页面表示,这是对MqMerge的修改,MqMerger是一种在从其他地方提取的新变更集上重新建立一系列补丁基础的技术。
然而,它涉及保存已经应用的修补队列的副本(实际上都是hg qsave does
(,并将保存的副本用作三向合并的引用的一部分,以实现修补队列的重新基准。在启用rebase扩展之前,我曾经自己做过这件事。然后,这只是在我想成为它的新父母的提示变更集上重新调整第一个补丁的基础。
但这不是你想要的,因为你想要的基本上是在你更改的补丁之上重新设置补丁的基础。不过,修补程序队列是线性的,只有当应用了修补程序的变更集有其他子级与修补程序队列平行时,才能重新设置修补程序的基础:
--- A -------- patch1 --- patch2
-- B
在上述情况下,补丁队列可以很容易地重新基于B
和hg rebase
(因此建议使用hg rebase
(,但这与您的情况无关。
解决您的情况的方法
以下是一个应用的补丁,其中包含未保存的本地更改,这些更改将与未应用的补丁冲突:
--- A --- patch1 <patch2>
-- [changes]
通常我会咬紧牙关,手动处理拒绝,因为拒绝通常很少。我发现,如果我遇到的情况是,有太多的拒绝需要手动处理,我可能一开始就没有正确地组织它们
如果使用qsave
和qpush -m
等的技术比以下技术更可取,则qsave
不太可能很快被删除,即使它已被弃用。
如果我真的想利用三向合并工具,以下是我将如何处理上述情况:
(TortoisHg2.x还不允许我们重新调整基本补丁队列,所以这是我有时会做的完成重新调整基本导入的变体。(
使用
qnew
将未保存的更改改为新补丁,而不是qrefresh
:--- A --- patch1 --- patch1b <patch2>
将这些补丁完成为常规变更集:
--- A --- B --- C <patch2>
更新到
patch
将干净应用到的变更集(B
(,并应用补丁:--- A --- B --- patch2 -- C
在
C
之上重新调整patch2
,以便使用基础B
:来解决本地patch2
和其他C
之间的冲突(在TortoiseHg 2.x中,我必须在重新定基之前完成
patch2
,然后将其导入回队列中。(--- A --- B --- C --- patch2
再次将
B
和C
作为补丁导入队列:--- A --- patch1 --- patch1b --- patch2
弹出
patch2
和patch1b
,然后将patch1b
折叠成patch1
(重命名为patch1new
(:--- A --- patch1new <patch2>
现在patch2
将干净地应用于patch1new
。
我最近一直在开发一个扩展来实现这一点,因为我使用了很多MQ补丁。该扩展名为qsmooth
(因为您可以"平滑"补丁(。
您可以在此处查看:https://bitbucket.org/jwdevel/qsmooth
它使用的过程与乔尔的回答非常相似。我还没有在生产中大量使用它,但它有相当多的测试,我很高兴收到错误报告。