如何合并分支上的功能和错误修复
简单地说,我有以下分支设置:
MAIN
|--- DEV
|--- PROD
大多数开发都是在 DEV 分支中完成的。当代码准备好测试时,所有内容都会合并到 MAIN 分支并发布到我们的测试环境。测试完成后,将完成与 PROD 的合并,并将所有内容发布到生产服务器。有时会对 MAIN 或 PROD 代码进行更改(主要是错误修复),但这是一个例外。
我被要求设计一个功能和错误修复合并的系统。这意味着 DEV 中的单独更改应跨 MAIN 和 PROD 合并。在我们当前的设置中,此信息会丢失:例如,功能 A、B 和 C 在 DEV 分支中实现。假设每个功能都有两个相应的变更集:A1、A2、B1、B2、C1、C2。按照我们目前的工作方式,所有内容都会一次性合并到 MAIN 分支。因此,当我们想要“精挑细选”必须从 MAIN 转移到 PROD 的功能时,我们不能这样做,因为 MAIN 上只有一个变更集:合并的签入。
你会如何解决这个问题?我需要改变我的分支策略吗?
我正在使用 TFS 进行源代码控制。
Simply put I have the following branch setup:
MAIN
|--- DEV
|--- PROD
Most developments are done in the DEV branch. When the code is ready to test, everything is merged to the MAIN branch and published to our test environment. When tests are completed, a merge to PROD is done and everything is published to the production server. Every now and then changes (mostly bugfixes) are made on the MAIN or PROD code, but this is an exception.
I have been asked to think out a system for feature and bugfix merging. This means that separate changes in the DEV should be merged across MAIN and PROD. With our current setup this information is lost: for example features A, B and C are implemented in the DEV branch. Let's say every feature has two corresponding changesets: A1, A2, B1, B2, C1, C2. With our current way of working, everything is merged to the MAIN branch in one go. So when we want to "cherry pick" features which have to go from MAIN to PROD we can't do this because there's only one changeset on MAIN: the checkin of the merge.
How would you fix this? Do I need to change something to my branching strategy?
I'm using TFS for source control.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您愿意,您可以编写一个工具来分析合并历史记录,但真正的答案是不要这样做。当您选择时,您将无法保证您在源分支中测试和稳定的代码将在目标分支中以相同的方式执行。有时这是可以的,但在您的情况下,它违背了在原始未经测试的开发签入和实时生产部署之间建立中间分支的整个目的。
正如我最喜欢的分支中所述/合并视频,你的指导原则应该是“向下合并,向上复制”。也就是说,每当需要解构和/或应用代码差异时,就让不稳定的分支受到影响。 (从集成的应用程序中挑选功能就是一个例子。)同时,向稳定分支(如 Main 和 Main 分支)升级的代码是一个很好的例子。产品应该始终是与您已经在源分支中努力稳定的内容相匹配的直接副本。听起来您目前正在遵循此策略;在面对樱桃选择时保留它将是我使用功能分支的第一大动机,甚至比使功能团队免受彼此破坏更重要。
正如 Jim 提到的,管理功能之间的依赖关系是一个问题。如果您可以提前识别它们,通常的解决方案是创建由具有共同依赖性的功能共享的子分支。
当然,软件并不总是按计划进行。如果需要共享代码的分支位于树的相对两侧(例如,如果功能 1 依赖于 LibA 和 LibB,但功能 2 不适合成为 B 的一部分,则这根本不起作用由于结构或技术原因)。
You can write a tool to piece through the merge history, if you like, but the real answer is don't do that. When you cherry pick, you lose any guarantee that the code you tested and stabilized in the source branch will perform the same way in the target branch. Sometimes that's ok, but in your case it defeats the whole purpose of having an intermediate branch sitting between raw untested Dev checkins and your live PROD deployments.
As discussed in my favorite branch/merge video, your guiding principle should be "merge down, copy up." That is, whenever the need arises to deconstruct and/or apply code diffs, let unstable branches take the hit. (Cherry picking features out of an otherwise integrated app is one example.) Meanwhile, code that's promoted up toward stable branches like Main & Prod should always be a straight copy that matches what you've already worked so hard to stabilize in the source branch. Sounds like you're following this strategy currently; preserving it in the face of cherry picks would be my #1 motivation for using feature branches, even moreso than insulating feature teams from each others' breakages.
Managing dependencies between features is an issue, as Jim mentioned. If you can identify them in advance, the usual solution is to make sub-branch(es) that are shared by the features with the common dependency.
Software doesn't always go as planned, of course. And this doesn't work at all if the branches that need to share code are on opposite sides of the tree (e.g. if Feature1 depends on LibA and LibB, but Feature2 is ill equipped to be part of B for structural or technical reasons).
我不认为这里有什么神奇的酱料,你只需要找到一个系统,在这个系统中,你可以对你可能想要挑选的每个单元的主要部分进行修订。
这可以通过单独合并每个修订版来轻松完成,这很痛苦,但可以满足您的需求。
或者,您可以通过一次将每个功能合并到主要功能中来提高粒度。这要求您按顺序处理功能,如果您独自一人,这可能没问题,但如果有几个人,这会很痛苦,因为您必须经历代码冻结,其中一些人已经完成并且其他人则没有。
您可能会发现也可能不会发现更易于管理的另一种工作方式是为每个功能创建一个 DEV 分支。从这个意义上说,不是拥有一个永远存在的 DEV 分支,而是拥有一组仅在功能完成之前存在的临时 DEV 分支。
每个 DEV 分支的重新整合将为您提供一个清晰的主版本,可以进行挑选。
您可以获得开发分支之间的依赖关系。假设分支 devA 需要分支 devB 的一些实现,您必须将 devB 所需的部分合并到 main 中,然后将它们合并到 devA 中。然而,devA 不应该需要 devB 未完成的工作,所以你(理论上)应该能够愉快地 RI 这些部分。当然,由于您选择了 PROD,因此不必发布这些部分集成。
考虑到您的分支策略,我想您已经找到了这一点,但如果没有,则值得一读:
http://branchingguidance.codeplex.com/wikipage?title=html&referringTitle=首页
I don't think there's any magic sauce here, you've just got to find a system where you have a revision on main for each unit you might like to cherry pick.
This can be done trivially by merging each revision individually, which is a pain, but gets you what you want.
Alternatively, you can up the granularity, by merging each feature into main one at a time. This requires that you work sequentially on features, which may be ok if you're on your own, but will be a pain if there's a few of you, since you'll have to go through a code freeze where some people have finished and others haven't.
Another way of working which you may or may not find more manageable is to have a DEV branch for each feature. In this sense, instead of having an ever existant DEV branch, have a collection of ephemeral DEV branches that only exist until the feature is completed.
The reintegration of each DEV branch will give you a clear revision in main which can be cherry picked.
You can get dependencies between dev branches. Say branch devA needs some implementation from branch devB, you'll have to merge the required parts of devB into main and then merge them down into devA. However, devA shouldn't be needing unfinished work from devB, so you should (in theory) be able to RI those parts happily anyway. And of course, since you're cherry picking into PROD, these partial integrations don't have to get published.
Given your branching strategy, I guess you've already found this, but if not, it's worth reading:
http://branchingguidance.codeplex.com/wikipage?title=html&referringTitle=Home