如何通过Mercurial管理并发发展?
-
02-10-2019 - |
题
这是一个最佳实践问题,我希望答案是“取决于”。我只是希望学习更多现实世界的场景和工作流程。
首先,我谈论的是同一项目的不同变化,所以请不要使用子雷。
假设您将代码库放在HG存储库中。您开始使用复杂的新功能A,然后您值得信赖的测试仪报告复杂的错误B(您有测试人员,对吗?)。
如果(修复)b取决于A,这是微不足道的。
我的问题是,当他们独立时该怎么办(或者至少现在看来)。
我可以想到以下方式:
- 为B使用单独的克隆。
- 在同一存储库中使用匿名或命名分支或书签。
- 使用MQ(在A顶部带有B补丁)。
- 使用分支的MQ(我稍后再解释)。
- 使用多个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):
hg qnew bugA
;对A进行更改;hg qref
mq branch branchA; hg qci
hg qpop; mq up -rtip^
hg qnew bugB
;对B进行更改;hg qref
mq branch branchB; hg qci
- 再次工作:
hg qpop; mq up branchA; hg qpush
采取这么多步骤似乎很疯狂,只要您需要切换工作,就必须 hg qci; hg qpop; mq up <branch>; hg qpush
. 。但是请考虑一下:您在同一存储库中有几个命名的发行分支,您需要同时处理几个项目和错误修复,以确保为此工作保证获得奖金)。其他方法很快就会迷路。
现在我的HG爱好者,还有其他/更好的选择吗?
(更新) qqueue
几乎使#4过时。参见史蒂夫·洛什(Steve Losh)的优雅描述 这里.
解决方案 2
似乎没有比我在问题中列出的选择更多或更好的选择。所以他们又来了。
- 每个项目使用一个克隆。
- 优点:总分离,因此在切换项目时没有重建。
- 缺点:工具链需要在两个克隆之间切换。
- 在同一存储库中使用匿名或命名分支或书签。
- 优点:标准HG(或任何DVCS)实践;干净利落。
- 缺点:必须在切换和重建之前提交。
- 每个项目使用MQ与一个补丁(或多个连续的补丁)。
- 优点:简单简便。
- 缺点:必须
qrefresh
在切换和重建之前;如果项目不是正交的,那么棘手和风险。
- 使用一个MQ分支(或
qqueue
每个项目为1.6+)。- 优点:超灵活和可扩展(对于并发项目的数量)
- 缺点:必须
qrefresh
和qcommit
在切换和重建之前;感觉很复杂。
像往常一样,没有银色子弹,因此请选择一项工作权。
(更新)对于任何爱上MQ的人,在常规分支(#2 +#3)上使用MQ可能是最常见和最可取的做法。
如果您在两个分支上有两个基线的并发项目(例如,下一个版本和当前版本),那么在这样的人之间跳舞很琐碎:
hg qnew; {coding}; hg qrefresh; {repeat}
hg qfinish -a
hg update -r <branch/bookmark/rev>
hg qimport -r <rev>; {repeat}
在最后一步, qimport
应该添加一个 -a
一次导入更改行的选项。我希望 Meister Geisler 注意到这一点:)
其他提示
我总是会使用命名分支机构,因为这让Mercurial可以完成工作:保留您的项目历史记录,并记住为什么您对源代码的顺序进行了哪些更改。至少考虑到我的工作风格,通常将一个或两个克隆坐在磁盘上通常很容易:
您的项目是否缺乏构建过程,以便您可以通过源代码进行测试和运行内容?然后,我将很想只有一个克隆,然后
hg up
当我需要在另一个分支上工作时,来回来回。但是,如果您有建筑物,虚拟或其他结构,并且可能在两个分支之间有所不同,则可以做一个
hg up
然后,等待重新运行的构建过程可能会很大,尤其是在涉及设置示例数据库之类的情况下。在这种情况下,我肯定会使用两个克隆,一个坐在后备箱的尖端,一个坐在紧急特色分支的尖端上。
因此,问题是,当您被告知停止在功能A上工作并开始独立功能B时,有哪些其他选择,用于:如何使用Mercurial管理并发开发?
让我们看一下删除并发性的问题,就像您编写螺纹代码一样 - 定义一个简单的工作流以解决给您的任何问题,并将其应用于每个问题。完成后,Mercurial将加入工作。因此,程序员A将在功能A上工作A。程序员B将在功能B上工作。两者都恰好是您。 (如果只有我们有多核大脑:)
我总是会使用命名分支机构,因为这让Mercurial可以完成工作:保留您的项目历史记录,并记住为什么您对源代码的顺序进行了哪些更改。
我同意布兰登的观点,但我想知道他是否忽略了该功能A尚未经过测试?在最坏的情况下,代码编译和通过单元测试, 但是某些方法实现了先前的要求,并且某些方法实现了新方法。 与上一次入住的差异是我使用的工具,可以帮助我通过功能A重回正轨A。
您的代码是否在通常会检查它的时候? 从功能A转换为功能B上的切换并不是将代码提交给头部或分支的理由。仅检查编译和通过测试的代码。 我的原因是,如果程序员C需要开始功能C,则该分支的新鲜结帐不再是最佳起点。 保持分支头保持健康,这意味着您可以通过更可靠的错误修复来快速响应。
目的是使您的(测试和验证)代码运行,因此您希望所有代码最终合并到头部(开发和旧分支)。我的观点似乎是,我看到分支的使用效率低下:代码变为陈旧,然后不使用,合并变得比原始问题更难。
只有您的选择1对我来说很有意义。一般来说:
- 在其他人看到它之前,您应该认为您的代码有效。
- 偏爱头上的分支。
- 分支并办理登机手续,如果其他人正在解决问题。
- 分支如果您的自动化系统或测试人员仅需要您的代码。
- 如果您是团队的一员,则分支问题。考虑一下头,请参阅1-4。
除配置文件外,构建过程应为结帐和单个构建命令。与新程序员一起加入项目,在克隆之间切换不应该更难。 (我承认我的项目需要在这里工作。)