Subversion 中有两种类型的合并:
- 三点合并
- 两点合并(又名重新整合合并)
假设您正在开发主干,并且您有一个特定的功能需要完成。您创建一个功能 A分支。当你处理这个特性时,你希望你在主干上所做的工作包含在特性 A中,这样你就可以跟上其他人所做的事情。Subversion 将使用三点合并。
Subversion 会从分支发生的那一点看主干和分支特性 A 之间的区别。最近的共同祖先。然后它会考虑对功能 A 所做的所有更改(您不想触摸)以及在主干上完成的代码更改。
然后 Subversion 将合并主干上的更改,而不会覆盖在分支上所做的更改。标准的合并程序,Subversion 做得很好。
从哪里svn:mergeinfo
进来?您不想合并两次相同的更改,因此 Subversion 使用svn:mergeinfo
属性跟踪更改。如果 Subversion 发现来自 Revision 5 的主干中的更改已经被合并,它不会重新合并该更改。这很好。
现在,您已经完成了您的功能,并且您希望将这些更改合并回主干。您将最后一个主干合并到分支合并,提交这些更改,然后从功能分支合并回主干。
这里有点问题。我们通过svn:mergeinfo
. 但是,由于我们还没有从 Feature 分支合并到主干,所以没有svn:mergeinfo
。如果我们尝试从 Feature 分支进行正常的三点合并到主干,主干将假定 Feature 分支中的所有更改都应该合并回主干。但是,其中许多功能实际上是已合并的主干更改。
老实说,此时,我们想做一个两点合并。一旦我们进行合并,我们希望主干和功能分支完全匹配。毕竟,我们现在已经定期将主干合并到功能分支中。我们想要做的是将这些功能重新合并到主干中。因此,主干将与功能分支相同。
在 Subversion 1.8 之前,您必须通过运行来强制重新集成合并svn merge --reintegration
。现在,Subversion 将查看合并历史并确定何时应该进行重新集成合并。
现在这是棘手的部分。仔细查看修订号。这些将非常非常重要!
- 修订版 10:我对 Trunk 进行了最后的更改,我需要将这些更改合并到 Feature 分支中。
- 修订版 11:我将主干合并到功能分支中。
svn:mergeinfo
将显示从 Revision 1 到 Revision 10 的所有主干都在 Feature 分支中。由于主干上的最后一次更改是修订版 10,因此这非常有意义。
- 修订版 12:我将功能分支的修订版 11 合并到主干中。这是重新整合合并。在此之后,功能分支上的内容和主干中的内容应该完全一致。
现在,这是踢球者!
现在,我想将它合并到我的 Feature 分支(创建 Revision 14)。现在,svn:mergeinfo
功能分支上的内容是什么?它表示从 Revision 1 到 Revision 10 的主干已合并到 Feature 分支中。但是,主干的修订版 12 和修订版 13 还没有。因此,Subversion 将希望将 Revision 12 和 Revision 13 合并回 Feature 分支。
但是等一下!
主干上的修订版 12 是我将功能分支中的所有更改合并回主干!也就是说,Revision 12 已经包含了我在 Feature 分支中所做的所有修订更改。如果我将修订版 12 合并回我的功能分支,我会说修订版 12 中主干上的所有这些更改(实际上是在功能分支上进行的更改并合并到主干)需要合并到功能分支中。但是,这些更改也是在 Feature 分支上进行的。你能说合并冲突吗?我知道你可以!
有两种处理方法:
- 推荐的方法:将功能分支重新集成回主干后,删除该分支。锁定它。永远不要再使用它。不要碰!这并不像听起来那么糟糕。重新集成合并后,您的主干和该功能分支无论如何都会匹配。从主干删除和重新创建分支不会那么糟糕。
- 棘手的工作方式:我们需要做的是让 Subversion 认为 Revision #12(或重新集成合并更改)已经合并到我们的 Feature 分支中。我们可以和这处房产混在一起
svn:mergeinfo
。而且,我过去就是这样做的。它说的地方trunk:1-11
,我会手动将其更改为trunk:1-12
.
这很棘手,但是太棘手了,而且有风险,因为 Subversion 已经为您提供了一种svn:mergeinfo
无需手动更改即可操作的方法。
这称为仅记录合并。
$ svn co svn://branches/feature_a
$ cd feature_a
$ svn merge --record-only -c 12 svn://trunk
$ svn commit -m "Adding in the reintegration merge back into the feature branch."
这会更改svn:mergeinfo
功能分支上的内容,而不会影响文件的实际内容。没有进行真正的合并,但 Subversion 现在知道主干的修订版 12 已经在 Feature 分支中。一旦你这样做了,你就可以重用特性分支。
现在看看您的图表:当您将分支 B 合并到分支 A 时,您将 B 中的所有更改合并到 A 中,并对其svn:mergeinfo
进行了跟踪。当您将分支 B 合并回分支 A 时,您已经在分支 A 中拥有来自分支 B 的所有更改,并且您不希望将这些更改带回分支 B。您应该使用重新集成合并:
$ cd $branch_a_working_dir
$ svn merge $REPO/branches/B
$ svn commit -m "Rev 7: All of my changes on Branch B are now in A"
$ vi d.txt
$ svn add d.txt
$ svn commit -m"Rev 8: I added d.txt"
$ cd $branch_b_working_dir
$ svn merge --reintegrate svn://branch/A # Note this is a REINTEGRATION merge!
$ svn commit -m"Rev 9: I've reintegrated Branch A into Branch B
现在,如果我们想继续使用分支 A 进行进一步的更改:
$ cd $branch_a_working_dir
$ svn merge -c 9 --record-only $REPO/branches/b
$ svn commit -m"I've reactivated Branch A and can make further changes"
我希望这能解释一下它是如何svn:mergeinfo
工作的,为什么你必须知道你是使用普通的三点合并还是两点重新整合合并,以及如何在你完成后重新激活一个分支重新整合合并。
只要您牢记这一点,Subversion 合并就可以很好地工作。