Mercurial 工作流程建议
我正在寻求一些关于使用 Mercurial 的建议。
目前,我们在中央服务器上使用 CVS,并维护一个头分支和几个过去版本的分支。我们的工作流程是所有修复/新功能都在 HEAD 上实现,然后在任何分支上创建版本时,我们将有效地挑选和选择我们需要包含在分支上的文件,并移动分支标签以合并这些文件,然后去构建版本(并标记它)。
我想在 Mercurial 中实现类似的工作流程。但是,我不确定是否可以从默认分支中选择特定的修复(更改集)并将它们应用到我的发布分支之一。我所看到的是人们对其分支进行修复,然后将它们拉入默认分支。有没有一种方法可以使用 Mercurial 模仿上述 CVS 工作流程?
I'm after a bit of advice for using Mercurial.
We currently use CVS on a central server, and maintain a head branch and a couple of past version branches. Our workflow is that all fixes/new features are implemented on the HEAD, and then when creating releases on any of the branches, we would effectively pick and choose the files we require to be included on the branch, and move the branch tag to incorporate these files, then go and build the release (and tag it).
I'd like to implement a similar workflow in Mercurial. However, I'm not sure it would be possible to pick and choose specific fixes(changesets) from the default branch and apply them to one of my release branches. What I have seen is people applying fixes to their branches and then pulling these into the default branch. Is there a way I can mimic our CVS workflow as described above using Mercurial?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这在很大程度上取决于您的“过去版本分支”的实际情况,但我认为您在迁移时应该采用不同的工作流程。
将合并分支想象为合并河流:合并后,其中的所有内容也都在另一条中。这就是为什么如果您想要实现一个应在多个分支中结束的功能,建议的方法是在其中一个分支中实现它,然后将其合并到其他分支中。理解源分支中的所有内容都将最终出现在目标分支中非常重要,而不仅仅是您实现的功能。
因此,将过去的版本分支形成 matryoshka doll 是合理的。例如,您有三个长期分支:
1.x
、2.x
和default
。1.x
中的所有功能也存在于2.x
和default
中,2.x 中的所有功能
也存在于default
中。 (这里,default
是下一个主要版本的阶段;当您发布 v3.0 时,您会创建一个新分支3.x
。)因此,如果您想要
1.x
中的一个新功能,您可以在那里实现它,然后进行两次合并:1.x
合并到2.x
,然后2.x
进入default
(这是向前移植)。如果您尝试以相反的方式进行操作,在default
中(即向后移植),您将无法合并default
进入1.x
或2.x
,因为default
有很多其他内容不应该出现在旧版本中。很难逆流而行,因此您必须将必要的更改移植回1.x
和2.x
,这很可能不会完全应用,您基本上将手动完成 Mercurial 可以为您做的事情。您可以查看 Python 存储库的布局,开发指南中对此进行了解释< /a>.
It heavily depends on what your 'past version branches' actually are, but I think you should adopt a different workflow when migrating.
Think of merging branches as of merging rivers: everything that was in one is in the other as well, after you merge. That's why if you want to implement a feature that should end up in several branches, the suggested way is that you implement it in one of them, and then merge it into others. It's very important to understand that everything that was in the source branch will end up in the target branch, not just the feature you implemented.
So it's reasonable to have past version branches to form a matryoshka doll. For example, you have three long-lived branches:
1.x
,2.x
, anddefault
. All of the features in1.x
are also present in2.x
anddefault
, all of the features in2.x
are also present indefault
. (Here,default
is a stage for your next major version; you create a new branch3.x
when you release v3.0.)So, if you want to make a new feature in
1.x
, you implement it there and then do two merges:1.x
into2.x
, then2.x
intodefault
(this is forward-porting). If you try to do it the other way round, indefault
(that's back-porting), you won't be able to mergedefault
into either1.x
or2.x
, becausedefault
has a lot of other stuff that shouldn't appear in older version. It's hard to go against the flow, so you'll have to transplant the necessary changes back to1.x
and2.x
, which most probably won't apply cleanly, and you'll be basically doing by hand things that Mercurial could do for you.You may take a look at the layout of the Python repository, explained in the dev guide.
根据我的经验,以及我对集体分布式版本控制用户体验的理解,问题在于,挑选变更集是(实际上一直是)合并冲突的根源。本质上,通过尝试对最新代码实施更改并将其“向后移植”到旧代码,您会迫使自己必须一遍又一遍地重做相同的合并。
假设您正在维护三个版本 Head、Head-1 和 Head-2。在 Head-1 中,您实施了一项重大的重构更改。现在,您在 Head 中实现了三个新功能,并希望将其包含在 Head-1 和 Head-2 中。由于 Head 和 Head-1 都有相同的大重构,因此将新功能合并到 Head-1 中不会那么复杂。但是,要合并 Head-2 中的新功能,您可能必须解决所有三个功能之间完全相同的合并冲突,以绕过主要重构。
事实是,您可能已经在这样做了——您只是没有意识到这一点,因为 CVS 也无法帮助您进行另一个方向的合并。 Mercurial 和 Git 等较新的版本控制系统可以使“向前”方向的合并变得非常容易。
因此,与其在 Mercurial 中实现 Head 中的三个功能,不如实现 Head-2 中的更改。由于合并信息已在图模型中捕获,因此很可能合并到 Head-1,然后合并到 Head 将非常容易。
我并不是说您所要求的事情无法完成 - 您可以使用诸如移植扩展之类的东西来实现您的模型 - 如果您这样做,您只是无法利用 Mercurial 出色的合并能力你将为自己和你的团队做更多的工作。
In my experience, and in my understanding of the collective distributed version control users' experience, the problem is that cherry picking changesets is (and actually always has been) a recipe for merge conflicts. Essentially, by trying to implement changes on the newest code and "backport" them to older code, you're forcing yourself to have to redo the same merges over and over again.
Imagine that you are maintaining three releases Head, Head-1, and Head-2. In Head-1 you implemented a major refactoring change. Now you implement three new features in Head that you want to include in Head-1 and Head-2. Since Head and Head-1 both have the same big refactoring, the merge of the new features into Head-1 won't be all that complicated. However, to merge the new features in Head-2, you'll potentially have to resolve the exact same merge conflicts across all three features to get around the major refactor.
The truth is, you're probably already doing this -- you're just not aware of it because CVS doesn't help you with the merges in the other direction either. Newer version control systems like Mercurial and Git can make the "forward" direction merging much, much easier.
So instead of implementing the three features in Head in Mercurial, it would be better to implement the changes in Head-2. Since the merge information is already captured in the graph model, most likely the merges to Head-1 and then Head will be quite easy.
I'm not saying that what you're asking for can't be done -- you could use things like the transplant extension to implement your model -- you just wouldn't be taking advantage of Mercurial's excellent merging power if you do so and you would be making a lot more work for yourself and your team.