SVN之分支合并(left,right,working)

昨天在合并分支时遇到了这样一个问题:

我需要将一个开发分支51合并到主干分支trunk,在合并时出现了冲突,如下图:

1563411906336

当然,第一个文件(修订号为417975)是目前trunk下的最新版本号。第三个文件(修订号为417985)是目前dev51分支下的修订版本。到这里都好理解,但却出现了left版本(修订号为417812),修订号早于这两个版本,这是什么原理(⊙ˍ⊙)?


在朋友(这里手动感谢宝哥😄)的帮助下找到了这篇issue,https://stackoverflow.com/questions/7679113/differences-between-svn-merge-left-right-working-files-after-conflicts

在这个问题中,题主也遇到了类似的问题

1563412342110

下面有一个解答非常好,这里先直接可耻的CV下来😄,然后再做理解性概括。

Let’s say there are two branches, and last (HEAD) revision in branch A is 9, while it is 6 in branch B.

When cd B; svn merge -r 5:8 ^/braches/A is ran, svn will try to apply delta between 5 and 8 from branch A on top of branch B.

(In other words, changesets 7 and 8 will be applied to B)

1
2
3
4
5
6
7
common
ancestor left right
(1)━━┱───(3)──(5)──(7)──(8)──(9) # branch A
┃ └┄┄┄┄┬┄┄┄┄┘
┃ ↓
┗━(2)━━(4)━━(6) # branch B
working

If the delta applies cleanly, it’s all good.

Let’s say some lines were modified in changeset 3, and same source lines were modified differently in changeset 4.

If delta (5→8) doesn’t touch those lines, all is still good.

If delta (5→8) also modified what 3 and 4 did, changes cannot be merged automatically, and svn leaves a file in conflict state:

  • file — file with (working,left,right) delimited
  • file.working — state of file in branch B@6
  • file.merge-left — state of file in branch A@5
  • file.merge-right — state of file in branch A@8

If you edit such a file manually, you have a few choices — keep “working” (your version), keep “right” (their version; the other branch version) or merge the changes manually.

“Left” is not useful in itself, there’s no point to keep “left” (their old version) in the file.

It is, however, useful for tools. “left→right” is the changeset.

When you see, for example:

1
2
3
4
5
6
7
<<<<<<< .working
foo = 13
||||||| .merge-left.r5
foo = "13"
=======
foo = "42"
>>>>>>> .merge-right.r8

It tells you that "13" was changed to "42" in branch A.

Branch B had 13 (integer, not a string).

Most likely, your manual merge choice will be to change 13 to 42 and keep it an integer.

另一个回答:

file.merge-left.r4521 is the latest change of this file in the left branch (i.e. the origin) before the right branch (the destination) were created.

In other words, merge-left.r4521 it’s the first version of the file to be merged

with merge-right.r5004 (the latest version of the destination branch)

For example, say you want to merge branches Left and Right as below:

1
2
3
4
5
6
7
8
9
Left   1   2   f.3   4   f.5   6    7    f.9    11 

Right 8 f.10 f.12 13

Right is created in 8 ( is a copy of 7 )
file 'f' has been modified in 3, 5, 9, 10, 12
The merge of file 'f' will occur between 7 and 13 because
7 is the latest version of file f in Left before Right was created
13 is the latest version of Right

概括一下:

上面所说的branch B就可以看作我的trunk,branch A可以看作我的dev51分支。

cn_logo.png在417812版本进行了第一次修改,trunk可理解为在417975,也就是最新版本对这个文件也进行了修改。而目前的dev51版本的最新版本号为417985。

1
2
3
4
5
cn_logo.png━━┳━━━(?)━━━(417975)                         # trunk
left ┃ ↑
(417812) ┃ ┌┄┄┄┄┄┄┄┄┄┄┄┴┄┄┄┄┄┄┄┄┄┄┐
┗━ ━ ━ ━(?)━ ━ ━ ━ ━ ━ ━ ━(417985) # branch dev51
right

如上图所示,如果在开发分支的多个版本多次修改了一个文件,而主干分支也在某个版本修改了同一个文件的同一行,那么便会出现冲突。

那么,冲突发生时出现的left以及right分别对应哪个版本呢?

答案是,以创建分支时的主干版本作为left,以最后一次提交的分支版本作为right。及合并操作是发生在这两者之间。因为417812是dev51分支创建前的最后一个版本。