如何用mercurial管理并发开发?

Geo*_*eng 17 workflow mercurial dvcs mercurial-queue

这是一个最佳实践问题,我希望答案是"它取决于".我只是希望了解更多真实世界的场景和工作流程.

首先,我在谈论同一个项目的不同变化,所以请不要再使用subrepo.

假设您在hg存储库中拥有代码库.您开始处理复杂的新功能A,然后由您的可信测试人员报告复杂的错误B(您有测试人员,对吧?).

如果(修复)B取决于A,那将是微不足道的.你可以ci A然后ci B.

我的问题是当他们独立时(或至少现在看来)该怎么做.

我可以想到以下几种方式:

  1. 为B使用单独的克隆
  2. 在同一存储库中使用匿名或命名分支或书签.
  3. 使用MQ(在A之上使用B补丁).
  4. 使用分支MQ(我稍后会解释).
  5. 使用多个MQ(自1.6起)

1和2 由@Steve Losh 的优秀博客覆盖,该博客与一个稍微相关的问题相关联.

与其他选择相比,1的一个巨大优势是,当您从处理一件事物到另一件事物时,它不需要任何重建,因为文件是物理上分离且独立的.所以它真的是唯一的选择,例如,A和/或B接触定义三态布尔的头文件,并被数千个C文件包含(不要告诉我你没有看到这样的遗留代码基础).

3可能是最简单的(在设置和开销方面),如果B是一个小的和/或紧急修复,你可以翻转A和B的顺序.但是,如果A和B接触相同的文件,它会变得棘手.如果A和B的变化在同一个文件中是正交的,那么很容易修复无法应用的补丁,但从概念上讲它仍然有点风险.

4可以让你头晕,但它是最强大,最灵活和可扩展的方式.我默认hg qinit使用,-c因为我想标记正在进行中的补丁并推送/拉取它们,但它确实需要一个概念上的飞跃才能意识到你也可以在MQ repo中进行分支.以下是步骤(mq = hg --mq):

  1. hg qnew bugA; 为A做出改变;hg qref
  2. mq branch branchA; hg qci
  3. hg qpop; mq up -rtip^
  4. hg qnew bugB; 为B做出改变;hg qref
  5. mq branch branchB; hg qci
  6. 再次使用A: hg qpop; mq up branchA; hg qpush

采取这么多步骤似乎很疯狂,每当你需要切换工作时,你必须这样做hg qci; hg qpop; mq up <branch>; hg qpush.但请考虑一下:您在同一个存储库中有多个命名的发布分支,并且您需要同时处理多个项目和错误修复(对于这类工作,您最好获得保证奖励).使用其他方法很快就会迷路.

现在我的同伴爱好者,还有其他/更好的选择吗?


(更新)qqueue几乎使#4过时了.请参阅Steve Losh 在这里的优雅描述.

Bra*_*des 7

我总是使用命名分支,因为这可以让Mercurial完成它的工作:保存项目历史记录,并记住你为什么要对源代码做出哪些更改.考虑到我的工作风格,至少是否有一个或两个克隆坐在磁盘上通常很容易:

  1. 您的项目是否缺少构建过程,以便您可以从源代码中测试和运行事物?然后我会想要只有一个克隆,hg up当我需要在另一个分支上工作时来回.

  2. 但是如果你有buildout,virtualenv或其他构建的结构,并且可能在两个分支之间出现分歧,hg up那么等待构建过程重新运行可能是一个巨大的痛苦,特别是如果像设置这样的事情涉及一个示例数据库.在那种情况下,我肯定会使用两个克隆,一个坐在行李箱的顶端,一个坐在紧急功能分支的顶端.


Geo*_*eng 3

似乎没有比我在问题中列出的更多或更好的选择了。所以他们又来了。

  1. 每个项目使用一个克隆。
    • 优点:完全分离,因此切换项目时无需重建。
    • 缺点:工具链需要在两个克隆之间切换。
  2. 在同一存储库中使用匿名或命名分支或书签。
    • 优点:标准汞(或任何 DVCS)实践;干净利落。
    • 缺点:必须在切换前提交并在切换后重建。
  3. 每个项目使用 MQ 和一个补丁(或多个连续补丁)。
    • 优点:简单易行。
    • 缺点:必须qrefresh在切换之前和之后重建;如果项目不正交,就会很棘手且有风险。
  4. 每个项目使用一个 MQ 分支(或qqueue在 1.6+ 中)。
    • 优点:超灵活和可扩展(针对并发项目的数量)
    • 缺点:必须qrefreshqcommit切换之前和之后重建;感觉很复杂。

与往常一样,没有灵丹妙药,因此请挑选适合工作的灵丹妙药。


(更新)对于任何热爱 MQ 的人来说,在常规分支 (#2 + #3) 之上使用 MQ 可能是最常见和最好的做法。

如果您有两个并发项目,其基线位于两个分支(例如下一个版本和当前版本),那么在它们之间跳转很简单,如下所示:

hg qnew; {coding}; hg qrefresh; {repeat}
hg qfinish -a
hg update -r <branch/bookmark/rev>
hg qimport -r <rev>; {repeat}
Run Code Online (Sandbox Code Playgroud)

对于最后一步,qimport应该添加一个-a选项来一次导入一行变更集。我希望盖斯勒大师注意到这一点:)