【问题标题】:Conflict when attempting Undoing Changes example in Subversion在 Subversion 中尝试撤消更改示例时发生冲突
【发布时间】:2012-06-25 18:52:16
【问题描述】:

在探索 Subversion 中的功能时,我尝试测试svnbook 的分支和合并一章的基本合并部分的撤消更改小节中描述的用例。我使用的是 1.6.4 版本,但该部分的文本在本书的两个版本中是相同的。

在我的工作副本目录中,我编辑了一个文件 testcode.py,每次编辑添加一行,并在每次编辑后提交。多次提交后,文件内容如下:

this is my first import to trunk.  r1.

this is my first commit, first edit of testcode.py.  r2.

this is another edit of testcode.py.  r3.

this is an edit of testcode.py.  i'll get rid of this one.  r4.

this is another edit of testcode.py.  keeping it.  r5.

yet another edit.  keeping it.  r6.

存储库中的修订号与文件中的行匹配,因此在 /trunk/testcode.py@rN 中,文件的最后一行是以 rN 结尾的。我想要做的是删除以 r4 结尾的行,保持之前和之后的所有内容不变。

按照 svnbook 的 Undoing Changes 部分中的示例,我运行命令

svn merge -c -4 file:///path_to_repos/trunk

这会产生冲突(在运行该命令时,而不是在提交时),其中合并左文件包含直到第 r4 行的所有内容,而合并右文件包含直到第 r3 行的所有内容。换句话说,该命令不是删除过去的更改,而是希望将整个文件恢复到修订版 3 或 4,从而删除后续修订版(在本例中为 5 和 6)中的更改。

我在 svnbook 中阅读示例的方式是,用户撤销在修订版 303 中提交的更改并将结果提交到修订版 350 且没有冲突,我运行的命令应该生成了一个 svn 状态为 M 的文件保留除以 r4 结尾的所有行。

我是否错误地阅读了书中的示例,示例是否错误,或者是否有其他形式的用户错误我没有意识到?

【问题讨论】:

  • 绝对可重现。现在需要想想为什么会这样。
  • 使用svn diff -c -4 foo.txt > foo.patch 创建补丁,然后将其应用到foo.txt@HEAD 可以正常工作 - 删除 r4 行。
  • 所以补丁可以工作,但是“svn merge 的一个非常常见的用例”,正如 svn 书所说,一个简单的有自己的小节的,只是简单的没有不。这不会激发人们对 Subversion 的合并功能在更复杂的过程(例如重新集成分支)中的行为的信心。
  • SVN 合并是所有主要身体部位的痛苦——每个使用 SVN 的人都知道这一点。我没有足够的时间来检查在这种情况下发生了什么,但这是出乎意料的。我的直觉是它与在文件末尾进行的更改有关,但是,我还没有检查它。
  • 好的,刚刚检查了如果在文件中间添加行会发生什么 - 而不是在末尾。工作正常 - 没有冲突。

标签: svn merge


【解决方案1】:

基本问题是 Subversion 的 diff 算法以一种不一定直观的方式处理文件开头和结尾的更改。您的示例遇到了这种极端情况,而野外的大多数变化都没有。考虑一系列提交后看起来像这样的文件:

later commit (r5)
change to be reverted at beginning of file (r2)
initial commit (r1)
change to be reverted in middle of file (r3)
initial commit (r1)
change to be reverted at end of file (r4)
later commit (r5)

尝试将提交还原到文件的开头或结尾(示例中的修订版 2 和 4)会产生冲突。将更改还原到文件的中间可以按预期工作。

从概念上讲,将变更集视为具有由周围线条限制的范围可能会有所帮助。对文件中间的更改以周围未更改的行为界。文件开头或结尾处的更改范围一直延伸到文件的开头或结尾无论该点随后移动多远

因此,在上面的示例中,修订版 5 中添加的第二行正好位于修订版 4 范围的中间。就像您在此处期望恢复修订版 10 的冲突一样,因为修订版 11 中的更改在其中有一点点:

...                    <-- Line unchanged by revision 10, bounding its scope
line from revision 10  <--\
line from revision 11     | Revision 10's scope
line from revision 10  <--/
...                    <-- Line unchanged by revision 10, bounding its scope

出于同样的原因,您应该预料到这里会发生冲突:

...                    <-- Line unchanged by revision 10, bounding its scope
line from revision 10  <--\
line from revision 11     | Revision 10's scope
<EOF>                  <--/ (No unchanged line bounding the scope this direction)

请注意,这只是对为什么文件的开头和结尾看似不同的原因的概念解释,而不是理解 Subversion 合并过程的全面解释。

【讨论】:

  • 非常有趣且 100% 可重现。谢谢!您是否通过实验发现了这一点,您是否编写了 diff 算法,或者这是否记录在某处?我可能会考虑在我的文件的开头放置一个“虚拟”行,尤其是在结尾处。
  • 这只是经验。实际上,我努力寻找要包含在此答案中的文档,但找不到任何东西。
  • 只是为了确保我完全理解,我可以说以下吗?变更集的第一行(最靠近顶部)和最后一行(最靠近底部)定义了它的“范围”。如果更改的第一行是文件中的第一行(或最后一行),则范围将“永远”扩展到顶部/底部。并且:如果在后续提交中在该更改集的范围内发生任何更改,则原始更改集无法在不产生冲突的情况下撤消。对或错? :)
  • True,如果更改集完全由相邻的行组成。如果您在文件中的多个点更改片段,您将获得多个范围,而不是从第一个更改的行延伸到最后一个大范围。
猜你喜欢
  • 2010-09-07
  • 2013-12-21
  • 1970-01-01
  • 1970-01-01
  • 2012-10-28
  • 2021-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多