前向合并与后向合并的区别(Difference between Forward Merge and Backward Merge)

在使用SVN时,描述“前向合并”与“后向合并”的最简单方法是什么?

What's the simplest way to describe a "Forward Merge" vs. a "Backward Merge" when using SVN?

最满意答案

前向合并后向合并是什么意思? 我可以想到两个可能的含义:

我将更改(或更改)合并到分支或主干中,现在我想撤消该更改。 我将我的主干合并到一个分支(向前合并?),现在我想将我的分支合并回我的主干(向后合并?)。

在第一个背景下:

我在版本12345中对我的存储库进行了更改。此更改无效,现在我想撤消该更改:

$ svn merge -c -12345 .

这是一个反向合并,我将从Subversion中删除一个特定的更改。 这相当于命令:

$ svn merge -r12345:12344 .

在第二个背景下:

合并时,通常会执行所谓的三向合并。 我创建了一个分支来实现一些功能。 在我工作时,我希望在我的分支机构中保留更改:

$ svn checkout $REPO/branches/mybranch . $ svn merge $REPO/trunk

这是一个三向合并,可以被认为是一个前向合并 。 我希望我在trunk上的更改放在我的分支上,但我不想消除我在分支上所做的更改。 为了做到这一点,Subversion将分支与主干分支与主干之间的最后一个共同祖先进行比较。

在分支看起来像这样之前想象一下我的文件:

one two three four five six

我的分支上的文件现在看起来像这样:

one foo foo four five six

我的主干上的文件现在看起来像这样:

one two bar four bar bar

通过比较文件的预分支版本,Subversion可以看到我在我的分支上更改了第二行和第三行。 通过比较预分支版本和我的主干,Subversion可以看到我在我的主干上更改了第三,第五和第六行。

Subversion只会将我的主干中的第五行和第六行合并到我的分支。 Subversion知道第二行只在我的分支上改变了,不应该被触及。 但是,Subversion可以看到我的分支和主干上的第三行都被更改了。 因此,它会说合并冲突,并问我是否需要第3行的中继版本或第3行的分支版本。

Subversion实际上比这更有点琐碎。 它不仅仅将分支和主干的头部与最后一个共同祖先进行比较,而是比较分支发生以来主干上的各个修订变化 。 Subversion这样做是为了防止我第二次合并更改。 它通过使用属性svn:mergeinfo 。

现在如果你一直在从主干到分支(正向合并?)的合并,你的分支包含发生在主干上的所有变化。 当我最终想要将我的功能分支合并回我的主干(向后合并?)时,进行三向合并是没有用的。 我将比较我的分支上的合并中继信息与中继本身。

Subversion通过执行双向合并而不是普通的三向合并来处理此问题。 这称为重新融合 。 在这种情况下,Subversion仅将我的分支与我的主干进行比较,并尝试使我的主干看起来就像我的分支。

由于Subversion跟踪合并的方式,因此存在实现问题,这就是为什么在执行此重新集成合并后需要非常小心重用分支的原因。 通常建议锁定或删除分支,如果确实需要再次分支,则从头开始重新创建分支。 还有另一种方法使用merge命令的--record-only参数来允许您重用分支。


因此,在一个上下文中, 向后合并是指撤消更改,这意味着正常更改可以被视为前向合并

在另一个上下文中,将在一个分支上或在主干上进行的更改合并到另一个分支被认为是向前方向,而向后合并则是在向另一个方向进行时。

那么,当你询问前向后向合并时,你在谈论哪种背景?

What do you mean by forward merge and backwards merge? I can think of two separate possible meanings:

I merged a change (or did a change) into a branch or the trunk, and now I want to undo that change. I merged my trunk into a branch (forward merge?), and now I want to merge my branch back into my trunk (backwards merge?).

In the first context:

I did a change in my repository back in revision 12345. This change isn't working out, and now I want to undo that change:

$ svn merge -c -12345 .

This is a reverse merge where I am removing a particular change from Subversion. This is equivalent to the command:

$ svn merge -r12345:12344 .

In the second context:

When you merge, you usually do what is known as a three-way merge. I created a branch to implement some feature. I want to keep the changes on my trunk in my branch as I do my work:

$ svn checkout $REPO/branches/mybranch . $ svn merge $REPO/trunk

This does a three-way merge and could be thought of as a forward merge. I want my changes on trunk to be placed on my branch, but I don't want to wipe out the changes I made on my branch itself. In order to do this, Subversion compares the branch to the trunk and to the last common ancestor between the branch and the trunk.

Imagine my file before the branch looked like this:

one two three four five six

The file on my branch now looks like this:

one foo foo four five six

and the file on my trunk now looks like this:

one two bar four bar bar

By comparing the pre-branched version of the file, Subversion can see that I changed lines two, and three on my branch. By comparing the pre-branched version with my trunk, Subversion can see I changed lines three, five, and six on my trunk.

Subversion will merge only lines five and six from my trunk to my branch. Subversion knows that line two was changed on my branch only and should not be touched. However, Subversion can see that line three was changed on both my branch and on trunk. Therefore, it will say there's a merge conflict and ask me if I want the trunk version of line #3 or the branch version of line #3.

Subversion is really a bit tricker than this. It doesn't merely compare the head of the branch and trunk with the last common ancestor, it compares the individual revision changes on the trunk since the branch happened. Subversion does this to prevent me from merging in changes a second time. It does this by using the property svn:mergeinfo.

Now if you have been merging from the trunk to the branch (forward merge?) all this time, your branch contains all of the changes that took place on trunk. When I finally want to merge my feature branch back into my trunk (backwards merge?), doing a three way merge is pretty useless. I would be comparing the merged trunk information on my branch against the trunk itself.

Subversion handles this by doing a two-way merge instead of a normal three way merge. This is called reintegration. In this case, Subversion compares only my branch to my trunk, and tries to make my trunk look like just like my branch.

There are implementation issues with this because of the way Subversion tracks merging which is why you need to be very careful about reusing a branch once you do this reintegration merge. It is usually recommended to lock or delete the branch, and if you do need the branch again, to recreate it from scratch. There's another method using the --record-only parameter of the merge command to allow you to reuse the branch.


So, in one context, the backwards merge refers to undoing a change which means that the normal change could be thought of as a forward merge.

In the other context, the merging of changes done on one branch or on the trunk to another branch is considered the forward direction, and the backwards merge is when you go the other direction.

So, which context are you talking about when you ask about forward and backwards merging?

更多推荐