2

每当我尝试在 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

我的结果是:

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

我知道 SVN 并不以合并友好而闻名,但我不得不假设在这种情况下这是我的错。感谢您的任何指示。

4

3 回答 3

9

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

如果我们一直运行您的脚本,直到您将“主干”复制到“分支/a”,我们会发现我们有一个混合修订的工作副本:

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

所以当你将'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.

在查看 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
------------------------------------------------------------------------

跳过有问题的合并,我们有一个“干净”的工作副本,没有混合修订,也没有本地修改。到目前为止,一切都很好:

>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

但是如果我们使用 svn mergeinfo 命令来预览哪些版本将被合并,我们注意到版本 2 是合格的:

>svn mergeinfo --show-revs eligible ^/trunk branches\a
r2
r4

但是等等,修订版 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
------------------------------------------------------------------------

当我们在修订版 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

所以我们用混合版本的 WC 到 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
------------------------------------------------------------------------

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.
------------------------------------------------------------------------

但是,您也可以使用 URL-to-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'

或者只是在原始脚本中的 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'

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

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

[2] 当然,即使使用这三个选项之一仍然会导致文本冲突,但这是意料之中的,因为我们在创建分支后对主干和分支上的“颜色”文件进行了不兼容的更改。

>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
于 2013-03-11T20:48:56.407 回答
1

看来问题在于使用本地svn copy而不是远程。

-svn copy trunk branches/a
-svn commit branches/a -m 'created branches/a'
+svn copy ^/trunk ^/branches/a -m 'server side copy from trunk to branches/a'
+svn update

虽然SVN 书说本地副本“不推荐使用技术”,但它没有将此列为原因。相反,它只是谈论廉价的服务器端副本、磁盘使用情况、时间等。

于 2013-02-21T16:07:01.257 回答
0

您演示的案例应该会产生正常的冲突,而不应该导致树冲突。

我怀疑您的用例正在执行子树合并(请注意 svn merge 命令中的子树路径)。所有的合并信息都只存储在您结帐的顶层

从'svn帮助合并':

 SOURCE specifies the branch from where the changes will be pulled, and
 TARGET_WCPATH specifies a working copy of the target branch to which
 the changes will be applied. Normally SOURCE and TARGET_WCPATH should
 each correspond to the root of a branch. (If you want to merge only a
 subtree, then the subtree path must be included in both SOURCE and
 TARGET_WCPATH; this is discouraged, to avoid subtree mergeinfo.)

以下片段显示了我认为您在避免子树合并时正在寻找的功能。它使用'svn switch'来避免子树合并和多个WC

export SVN_REPO=~/svntest
cd $SVN_REPO
rm -rf $SVN_REPO/*
svnadmin create repo
svn mkdir file:///$SVN_REPO/repo/trunk -m "created trunk"
svn mkdir file:///$SVN_REPO/repo/branches -m "created branches"
#
svn checkout file:///$SVN_REPO/repo/trunk wc
cd wc
echo red > colors
svn add colors
svn commit . -m 'created trunk/colors with red inside' 
#
svn cp file:///$SVN_REPO/repo/trunk file:///$SVN_REPO/repo/branches/a  -m 'created branches/a'
#
echo green >> colors
svn commit . -m 'added green to trunk/colors'
#
svn switch file:///$SVN_REPO/repo/branches/a .
echo blue >> colors
svn commit  -m 'added blue to branches/a/colors'
svn update
svn merge file:///$SVN_REPO/repo/trunk

结果:

Committed revision 1.
SVN_REPO/repo/branches -m "created branches"

Committed revision 2.

SVN_REPO/repo/trunk wc
Checked out revision 2.
 cd wc
 echo red > colors
 svn add colors
 A         colors
 svn commit . -m 'created trunk/colors with red inside'
Adding         colors
Transmitting file data .
Committed revision 3.

SVN_REPO/repo/branches/a  -m 'created branches/a'

Committed revision 4.

 echo green >> colors
 svn commit . -m 'added green to trunk/colors'
Sending        colors
Transmitting file data .
Committed revision 5.

SVN_REPO/repo/branches/a .
 U    colors
Updated to revision 5.
 echo blue >> colors
 svn commit  -m 'added blue to branches/a/colors'
Sending        colors
Transmitting file data .
Committed revision 6.
 svn update
Updating '.':
At revision 6.

Conflict discovered in '/home/jbellamy/svntest/wc/colors'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options: p
--- Merging r4 through r6 into '.':
 C    colors
--- Recording mergeinfo for merge of r4 through r6 into '.':
 U   .
Summary of conflicts:
  Text conflicts: 1
     svn diff
Index: .
===================================================================
--- .   (revision 6)
+++ .   (working copy)

Property changes on: .
___________________________________________________________________
Added: svn:mergeinfo
   Merged /trunk:r4-6
Index: colors
===================================================================
--- colors      (revision 6)
+++ colors      (working copy)
@@ -1,2 +1,6 @@
 red
+<<<<<<< .working
 blue
+=======
+green
+>>>>>>> .merge-right.r6
于 2013-02-21T16:24:38.657 回答