要合并工作,您需要两件事:
- 你需要两个分支之间有一个共同的祖先。
- 如果您将两个分支保持同步,则需要在两者之间进行定期合并。例如,我假设 3.1 上的所有工作都应该在 3.2 中。当您在两个分支中工作时,您应该将 3.1 的更改合并到 3.2 中。
发生合并冲突是因为合并是一种三向比较。将两个开发流(开发流可以指分支或主干)相互比较,并将它们与它们的最后一个共同祖先进行比较。想象一个文件,其中第 100 行在两个开发流中都发生了更改。从一个合并到另一个将导致冲突。
Subversion 不只是区分文件,它也区分目录。如果我在一个开发流中重命名一个文件(或移动它),然后我进行合并,它将在另一个开发流中重命名(或移动)。如果我在一个开发流中删除或添加一个文件,然后合并,它也会在另一个开发流中被删除或添加。
在 Subversion 中,如果我对两个开发流上的同一个文件执行两种不同的操作,就会发生树冲突。例如,我重命名了 3.1 和 3.2 分支上的文件。即使我将它们重命名为相同的名称,Subversion 也会将其视为冲突。
为了防止您的灾难再次发生:确保您的两个分支确实共享相同的祖先。为什么不从 3.1 分支分支 3.2,或者至少在分支 3.2 之前将 3.1 分支重新整合回主干。Subversion 通常非常擅长跟踪历史,但您需要确保分支共享共同的历史。
另一种是常规合并。您需要定期将 3.1 合并到 3.2 分支——甚至可能每天。这可以确保在 3.2 分支上工作的人在 3.1 中拥有他们需要的更改,并且不会重复工作。不断合并还可以使更改保持较小,并且当存在合并冲突时,它们更容易处理。记住这个svn mergeinfo
命令,它可以让你知道什么已经合并到 3.2 中,以及 3.1 上的什么还需要合并。您始终可以使用该--record-only
参数来防止将来合并考虑特定修订。例如,您修复了两个分支上的错误,您使用--record-only
以确保未在 3.2 上完成对 3.1 的修复。或者,如果您在 3.1 中进行了您不希望在 3.2 上进行的更改,请执行--record-only
将阻止您在下一次合并时考虑 3.2 分支上的更改。
现在要做什么?你需要解开你的工作。看看svn log
两个分支之间的一个。如果您看到两个分支上都发生了错误修复,请使用 asvn merge --record-only
让 Subversion 知道 3.1 分支上的特定更改也在 3.2 分支上完成(尽管是手动的)。查看文件移动和重命名,看看它们是如何在每个分支上完成的。
完成此操作后,一次将 3.1 的更改合并到 3.2 几个修订版,cherry pick 合并。确保 3.1 上的更改是您想要在 3.2 上进行的更改。
这是一个漫长的提取过程,但您需要完成。以此为一课来改进您的开发过程。
我们习惯使用听起来像您使用的类似系统。Trunk 被认为是原始的并且与我们的版本相匹配(它从来没有真正做到过)。我们不断丢失从一个版本到另一个版本的更改,因为当我们创建了一个新分支以及将前一个分支合并到主干时(或者我们只是丢失了分支所在的位置)。
分支就像孩子:你做了一个,你最好准备好照顾它,不要忘记它的去向。
我们切换到一个持续的开发过程。我们在主干上进行开发,然后在发布之前进行分支。分支点通常在我们完成该版本的所有功能时出现,我们现在正在修复错误。
发布在分支上完成。如果我们发现一个错误,我们将修复分支上的错误,然后只将该修订合并到主干(如果该错误也在主干上)。一旦发布完成,分支就会被锁定。如果我们需要做一个修补程序,我们可以将该分支重用于修补程序。
有时,我们有功能分支。当我们这样做时,我会确保我们不断地从开发流合并到该功能分支。这样,当我们最终将该功能重新集成回主干时,我们几乎没有冲突。
通过将分支保持在最低限度并跟踪我们从哪里分支,并进行不断的合并(例如在功能分支中),我们减少了合并冲突,并且不再有曾经困扰我们发布的问题。