Subversion分支/主干最佳实践-如何保持分支最新?

23

我的开发团队使用Subversion已经有一段时间了。我们管理主干和分支的方式如下:

  • 我们(几乎)总是从主干发布。

  • 每个发布都有自己的分支。

  • 当一个发布准备好进行QA测试时,我们将分支合并回主干,并为下一个发布创建一个新分支。

  • 开发人员从主干或分支中工作,但没有针对特定开发人员的分支。

最近,由于应用程序的一些重大更改,我们遇到了一些可怕的合并会话。这些不总是顺利的,在QA期间有时会出现Subversion未正确合并的问题。

一个解决方案可能是定期(例如每周)将主干更改合并到发布分支中,以确保分支中具有最新的主干更改。这样可以更接近实时地修复冲突。

你在这个问题上有什么经验?是否有标准的最佳实践?此外,您有没有一种好的方法来跟踪哪些修订版本已合并到分支中(在Subversion中进行良好的注释可能会解决这个问题)。

5个回答

15

首先,我认为在管理代码分支和发布方面,没有一种适用于所有情况的解决方案。但从我的角度来看,以下是针对您提出的几点:

  • 是的,我会经常将trunk中的更改合并到发布分支。较小的变更总是比一个大集成更易于管理。当然,这意味着您正在使用最新的、最稳定的代码进行工作。

  • 积极地教导人们如何良好地合并代码。制作更改的开发人员应该进行合并(或密切参与其中)。了解您正在接受的内容以及完成后它应该是什么样子。我经常看到人们在不真正知道自己在做什么以及预期结果的情况下运行集成。

  • 也许您希望拥有一个不是trunk的集成分支。可以每天测试该分支,并在引入问题之前捕获任何问题,以免破坏trunk并使所有人都感到恐慌。


我们是一个相对较小的团队(4名开发人员),因此我们总是让每个人参与合并(至少是相关人员)。听起来集成分支可能是一个不错的选择。 - jonstjohn
1
我不同意。在我所在的团队中,我总是为每个功能和错误分支,这是最好的选择。它有很多优点。没有理由不这样做。 - PositiveGuy
如果你使用的版本控制工具支持轻量级分支,比如Git,我会同意这种说法。但是对于Subversion或Perforce等工具,在进行简单的错误修复时,肯定需要更多的开销。所以,我的建议是将你的SVN仓库迁移到Git。 :) - Andy Hume

13
假设我对您的模型有了正确的理解:您在一个分支(从主干上)中开发项目的重大更改,这个分支可能会变得相当老。
您继续在主干上进行其他开发,主干始终保存着“实时”的软件,因此这些更改只是小更新和错误修复。当您将重要的开发分支合并回主干时,就会出现问题。
使用这种模型,您只能有效地管理两个产品版本,并且现在可能已经足够了,但无论如何都可能会在其他方面造成麻烦,并且如果您需要管理3或4个版本,则情况会变得更糟。我可以建议您反转工作方式吗?
为每个发布创建一个版本分支。这应该从主干(任何修订版)派生出来。修改版本分支的唯一方法是合并来自主干的修订版。
这意味着您可以主要在主干上工作,而不是在一个大的开发分支中工作。您也可以直接将错误修复应用于主干 - 因此您没有为下一个版本存储大型集成问题。要将错误修复发布到以前的版本,请将必需的主干修订版合并到相应的版本分支中。
这样,您可以将您想要发布的所有内容都保存在分支中,但只会实际发布您满意的内容,因为这是您合并到版本分支中的所有内容。
如果需要,您仍然可以接受开发分支,但可以使它们更有针对性和更小规模,例如单个功能而不是大型项目。
这将使您能够以理智的方式管理多个版本,并使用svn的合并信息来保持对每个发布版本中包含的内容的良好跟踪。

这是一个非常有趣的看法。唯一的缺点似乎是你需要大量地将主干合并到分支上。假设我正在处理发布版本x,并且它正在进行QA测试,每次我进行修复时,我都会提交到主干,然后必须将该修订版本合并到分支上,对吗? - jonstjohn
就是这样。通过这样做,您将在发布分支中拥有一个合并记录,说明主干中的修复已经合并到该版本中。我们在工作中使用此信息来构建修订版和版本的矩阵,精确标记哪些修订版属于哪些版本。 - Jim T
谢谢,吉姆。有趣的观点,这可能是我们的一个好解决方案。 - jonstjohn
嘿,吉姆,你介意看一下我的问题吗:http://stackoverflow.com/q/4934610/34022。我喜欢你的概念,但我不确定如何正确地将功能分支集成到主干和发布分支中。非常感谢。 - Marc

5
我们的经验是要清楚区分:
- 开发分支 - 合并分支(用于合并我们确定要投入生产的开发)
主干仅用于记录稳定发布版本,从中可以进行分支。
在“开发分支”中,我们可以管理重要更改,包括一些不会出现在下一个版本中的更改(因为太复杂,不能按时准备好,依赖其他后期开发等)。
“合并分支”代表完成发布所需的最终步骤(注意复数)。它发生在会议之后,所有需要交付的功能都得到验证。
我们只将确定要投入生产的内容合并到“合并分支”。我们继续使用该分支直到最终发布。

@VonC 你如何撤销在合并分支中不想要的更改?我认为你只会将准备好的更改合并到合并分支中,因此不需要的更改不会出现在合并分支中。这就是问题的起源,因为你想要提交的更改是建立在尚未提交的更改之上的。因此,你想要提交的更改将无法合并,因为它正在合并不存在于合并分支上的行/文件。 - dan carter
@VonC 考虑一个例子,你在开发分支上有一个名为 A 的类,有人想添加一些行为作为专业化,所以他们将 A 重命名为 ABase 并创建新的子类 B 和 C,B 在 A 中获取一些现有行为,C 创建一个替代行为,所有共同的行为都在 ABase 中。现在,另外一些人正在处理不同的任务,更改了现在存在于 B 中的现有行为。您想将第二个更改(对 B)交付给合并分支,而不是第一个更改,但合并分支中不存在 B。 - dan carter
@dancarter,我对你最后一个例子的细节有不同意见,它混合了演化和重构。我认为重构不适用于下一个发布版本的开发工作,而更适合长期努力,这意味着:在dev中对B进行的“第二次更改”(当仅存在A时)需要在A中回溯到一致性(或在具有A的专用dev分支中,然后合并到一致性)。试图同时进行两者(在A上进行演化和重构,都是为了下一个发布版本)似乎是不可持续的。 - VonC
@Vonc祝你好运,在手动回溯第二个更改后将Abase、B和C合并到合并分支。我猜你只需要通过用开发版本覆盖合并版本来解决冲突。问题是,任何优秀的开发人员都会不断地进行这些更改,以保持代码的良好状态,并扩展它以添加新功能。因此,每个发布版都将有数十个合并冲突。 - dan carter
@dancarter “因此,我更喜欢将主要开发放在主干上,并且只有在事情进入UAT后才进行分支” 是的!我同意 :) 参见 https://dev59.com/s3HYa4cB1Zd3GeqPPMD1#16384644,在那里我进行了类似的辩论。我刚刚意识到,我正在讨论我四年前的答案,当时我正在使用ClearCase UCM,并且有一个“Stream”的结构影响了我的回答:请参阅https://dev59.com/sW035IYBdhLWcg3wE71s#5636931的后半部分,或者https://dev59.com/v2kw5IYBdhLWcg3wdKQv#9880266。 - VonC
显示剩余10条评论

2
完全同意Andy的观点:没有“一刀切”的解决方案,但问题不应该是保持你的发布分支最新,而是相反的。
良好的变更控制应该使你的分支不易受到波动的影响。门控问题应该在发布分支上修复,然后立即合并到主干。准备好这个“合并”可能不容易,发布门控问题甚至可能不存在于主干上,但你仍需要进行分析和测试。
从你所说的情况来看,你正在开发你的分支,然后在发布前一次性将所有内容合并到主干上,并且只是交叉着手祈祷。我想知道你这样做是否引入了多少错误。

2
首先,我完全同意之前回答者所说的没有一种适合所有情况的解决方案。
在我们的情况下,我们有许多相对较小的应用程序,每个应用程序通常只有一个开发人员。当我们进行协作开发时,通常只有2到4个开发人员参与。
我们的一般政策是:
- 主干包含当前项目状态; - 我们使用分支来开发新功能、修复错误等。分支完成后会合并回主干; - 要发布,我们从当前主干创建一个标签并发布该标签。
Andy还提出了一个重要观点需要强调:“积极教导人们如何进行良好的合并。”许多,如果不是大多数,我们的问题似乎都源于糟糕的合并实践。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接