svn树冲突:我做错了什么?

alt*_*dky 2 svn merge tree-conflict

无论何时我尝试在SVN中合并,我都会遇到大量的树冲突.好吧,在这个示例脚本的情况下只有一个,但仍然.

#!/bin/bash
svnadmin create repo
svn checkout file://`pwd`/repo wc
cd wc
mkdir trunk branches
svn add trunk branches
svn commit -m 'created trunk and branches'
echo red > trunk/colors
svn add trunk/colors
svn commit trunk -m 'created trunk/colors with red inside'
svn copy trunk branches/a
svn commit branches/a -m 'created branches/a'
echo green >> trunk/colors
svn commit trunk -m 'added green to trunk/colors'
echo blue >> branches/a/colors
svn commit branches/a -m 'added blue to branches/a/colors'
svn update
svn merge ^/trunk branches/a
Run Code Online (Sandbox Code Playgroud)

我的结果是:

Checked out revision 0.
A         trunk
A         branches
Adding         branches
Adding         trunk

Committed revision 1.
A         trunk/colors
Adding         trunk/colors
Transmitting file data .
Committed revision 2.
A         branches/a
Adding         branches/a
Adding         branches/a/colors

Committed revision 3.
Sending        trunk/colors
Transmitting file data .
Committed revision 4.
Sending        branches/a/colors
Transmitting file data .
Committed revision 5.
Updating '.':
At revision 5.
--- Merging r2 through r5 into 'branches/a':
   C branches/a/colors
--- Recording mergeinfo for merge of r2 through r5 into 'branches/a':
 U   branches/a
Summary of conflicts:
  Tree conflicts: 1
Run Code Online (Sandbox Code Playgroud)

我知道SVN并不是因为合并友好而闻名,但我不得不假设在这种情况下,这是我的错.谢谢你的任何指示.

小智 9

您遇到的问题不是由于本地副本[1]本身造成的.问题在于,在修订版3中,您复制了一个混合修订的工作副本(http://svnbook.red-bean.com/en/1.7/svn-book.html#svn.basic.in-action .mixedrevs).

如果我们运行你的脚本,直到你将'trunk'复制到'branches/a',我们发现我们有一个混合修订工作副本:

>svn st -v
                 0        0  ?           .
                 1        1 pburba       branches
                 1        1 pburba       trunk
                 2        2 pburba       trunk\colors
Run Code Online (Sandbox Code Playgroud)

所以当你将'trunk'复制到'branches/a'时,你实际上是在复制trunk @ 1和trunk/colors @ 2:

>svn copy trunk branches\a
A         branches\a

>svn st -v
                 0        0  ?           .
                 1        1 pburba       branches
A  +             -        1 pburba       branches\a
A  +             -        2 pburba       branches\a\colors
                 1        1 pburba       trunk
                 2        2 pburba       trunk\colors

>svn ci -m "Copy mixed-rev trunk"
Adding         branches\a
Adding         branches\a\colors

Committed revision 3.
Run Code Online (Sandbox Code Playgroud)

在查看r3的详细日志时,我们可以清楚地看到这一点:

>svn log -v -r3
------------------------------------------------------------------------
r3 | pburba | 2013-03-11 15:31:23 -0400 (Mon, 11 Mar 2013) | 1 line
Changed paths:
   A /branches/a (from /trunk:1)
   A /branches/a/colors (from /trunk/colors:2)

Copy mixed-rev trunk
------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

跳过有问题的合并,我们有一个"干净"的工作副本,没有混合修订,也没有本地修改.到现在为止还挺好:

>svn st -v
                 5        5 pburba       .
                 5        5 pburba       branches
                 5        5 pburba       branches\a
                 5        5 pburba       branches\a\colors
                 5        4 pburba       trunk
                 5        4 pburba       trunk\colors
Run Code Online (Sandbox Code Playgroud)

但是,如果我们使用svn mergeinfo命令预览要合并的修订版本,我们会注意到revsion 2符合条件:

>svn mergeinfo --show-revs eligible ^/trunk branches\a
r2
r4
Run Code Online (Sandbox Code Playgroud)

但是等一下,revison 2是"颜色"的补充,

>svn log -v -r2
------------------------------------------------------------------------
r2 | pburba | 2013-03-11 15:43:52 -0400 (Mon, 11 Mar 2013) | 1 line
Changed paths:
   A /trunk/colors

created trunk/colors with red inside
------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

当我们在第3版中创建分支时,我们已经复制了它!那么为什么Subversion会再次尝试合并呢?原因可以追溯到我们制作的混合修订WC-to-WC副本.合并目标'branch/a'知道它是在添加'trunk/colors'之前从trunk @ 1复制的.因此合并认为修订版2尚未合并到branch/a并尝试合并此更改,将"colors"添加到"a"中,其中已存在同名文件,这会导致冲突:

>svn merge ^/trunk branches\a
--- Merging r2 through r5 into 'branches\a':
   C branches\a\colors
--- Recording mergeinfo for merge of r2 through r5 into 'branches\a':
 U   branches\a
Summary of conflicts:
  Tree conflicts: 1

>svn st
 M      branches\a
      C branches\a\colors
      >   local file obstruction, incoming file add upon merge
Summary of conflicts:
  Tree conflicts: 1
Run Code Online (Sandbox Code Playgroud)

所以我们用我们的混合修订WC-to-WC拷贝欺骗了Subversion,它在拷贝期间有效地将修订版2带到了分支.那么为什么Subversion不能检测到这个并跳过修订版2?在这种情况下,我们可以想象,但如果修订版2包含对"主干"的其他更改,该怎么办?例如:

>svn log -v -r2
------------------------------------------------------------------------
r2 | pburba | 2013-03-11 15:43:52 -0400 (Mon, 11 Mar 2013) | 1 line
Changed paths:
   A /trunk/colors
   A /trunk/README
   M /trunk

created trunk/colors with red inside, add a README file, and set the
svn:ignore property on trunk
------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

Subversion不支持将修订的一部分合并到给定路径,它可以是全有或全无.

~~~~~

那么如何避免这个问题呢?正如您已经发现的那样,执行URL到URL的复制可以解决它.为什么?因为当复制源是URL时,根据定义,它是一些统一的修订:

>svn log -v -r3
------------------------------------------------------------------------
r3 | pburba | 2013-03-11 16:02:59 -0400 (Mon, 11 Mar 2013) | 1 line
Changed paths:
   A /branches/a (from /trunk:2)

Create branch 'a' from 'trunk' with a URL-to-URL copy.
------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

但是,您也可以使用URL到WC副本完成相同的操作:

 svn commit trunk -m 'created trunk/colors with red inside'
-svn copy trunk branches/a
+svn copy ^/trunk branches/a
 svn commit branches/a -m 'created branches/a'
Run Code Online (Sandbox Code Playgroud)

或者只是在原始脚本中的WC到WC副本之前更新WC:

 svn commit trunk -m 'created trunk/colors with red inside'
+svn update
 svn copy trunk branches/a
 svn commit branches/a -m 'created branches/a'
Run Code Online (Sandbox Code Playgroud)

您的原始解决方案,URL到URL副本后跟更新,是IMO的最佳选择.更新和WC到WC副本以及URL到WC副本都允许在提交之前对副本进行其他更改 - 最好是创建分支的修订版本没有除了副本之外的其他变化.也就是说,所有这些选项都可以正常工作[2].

[1]在Subversion中,我们通常将此称为工作副本到工作副本,或简称WC到WC副本.将其与URL-to-URL,URL-to-WC或WC-to-URL副本进行对比.WC到URL的副本也容易受到上述问题的影响.另见'svn copy --help'.

[2]当然,即使使用这三个选项中的一个仍然会导致文本冲突,但这是预期的,因为我们在创建分支后对主干和分支上的"colors"文件进行了不兼容的更改.

>svn merge ^/trunk branches\a
--- Merging r3 through r5 into 'branches\a':
C    branches\a\colors
--- Recording mergeinfo for merge of r3 through r5 into 'branches\a':
 U   branches\a
Summary of conflicts:
  Text conflicts: 1
Conflict discovered in file 'branches\a\colors'.
Select: (p) postpone, (df) diff-full, (e) edit, (m) merge,
        (mc) mine-conflict, (tc) theirs-conflict, (s) show all options: p

>svn st
 M      branches\a
C       branches\a\colors
?       branches\a\colors.merge-left.r2
?       branches\a\colors.merge-right.r5
?       branches\a\colors.working
Summary of conflicts:
  Text conflicts: 1
Run Code Online (Sandbox Code Playgroud)