【发布时间】:2011-01-31 15:39:28
【问题描述】:
我喜欢从版本控制系统 (VCS) 中区分三种不同类型的冲突:
- 文本
- 句法
- 语义
文本冲突是由合并或更新过程检测到的。这是由系统标记的。在解决冲突之前,VCS 不允许提交结果。
句法冲突没有被 VCS 标记,但结果不会被编译。因此,即使是稍微细心的程序员也应该了解这一点。 (一个简单的例子可能是由 Left 重命名变量,以及由 Right 使用该变量的一些添加行。合并可能会有一个未解析的符号。或者,这可能会引入一个语义变量隐藏的冲突。)
最后,语义冲突没有被 VCS 标记,结果可以编译,但代码运行可能有问题。在轻微的情况下,会产生不正确的结果。在严重的情况下,可能会导致崩溃。即使是这些也应该由非常细心的程序员在提交之前通过代码审查或单元测试进行检测。
我的语义冲突示例使用 SVN(Subversion)和 C++,但这些选择与问题的本质并不真正相关。
基本代码是:
int i = 0;
int odds = 0;
while (i < 10)
{
if ((i & 1) != 0)
{
odds *= 10;
odds += i;
}
// next
++ i;
}
assert (odds == 13579)
左(L)和右(R)变化如下。
左的“优化”(改变循环变量的值):
int i = 1; // L
int odds = 0;
while (i < 10)
{
if ((i & 1) != 0)
{
odds *= 10;
odds += i;
}
// next
i += 2; // L
}
assert (odds == 13579)
对的“优化”(改变循环变量的使用方式):
int i = 0;
int odds = 0;
while (i < 5) // R
{
odds *= 10;
odds += 2 * i + 1; // R
// next
++ i;
}
assert (odds == 13579)
这是合并或更新的结果,SVN 没有检测到(这对于 VCS 来说是正确的行为),因此它不是文本冲突。请注意,它可以编译,所以它不是语法冲突。
int i = 1; // L
int odds = 0;
while (i < 5) // R
{
odds *= 10;
odds += 2 * i + 1; // R
// next
i += 2; // L
}
assert (odds == 13579)
assert 失败,因为 odds 是 37。
所以我的问题如下。还有比这更简单的例子吗?有没有编译后的可执行文件出现新崩溃的简单示例?
作为第二个问题,您在实际代码中是否遇到过这种情况?同样,特别欢迎简单的示例。
【问题讨论】:
-
这与 C++ 无关,因此我删除了该标签。老实说,我不明白这个问题,也看不出它与版本控制有什么关系。
-
rhubbarb 可能想听听其他人对这些语义变化的经验,这样他就可以建立一些在合并代码时需要注意的事项清单。如果这确实是重点的话,可能会成为一个有趣的话题。
-
@Tomislav:是的,这就是原因之一。 @Neil:我同意您删除 C++ 标签;我的错。另一方面,这与版本控制有一切。合并操作是 VCS 的核心,了解这些非常有用的系统偶尔会产生意外结果的方式也很重要。
-
@Neil:这让我想起了你在类似主题上的回答:stackoverflow.com/questions/1245431/…
-
您好,我们听取了您的要求,我们想出了一个工具,很可能解决部分问题:plasticscm.com/sm/index.html,我们现在开始内测。
标签: svn version-control conflict