I like to distinguish three different types of conflict from a version control system (VCS):
- textual
- syntactic
- semantic
A textual conflict is one that is detected by the merge or update process. This is flagged by the system. A commit of the result is not permitted by the VCS until the conflict is resolved.
A syntactic conflict is not flagged by the VCS, but the result will not compile. Therefore this should also be picked up by even a slightly careful programmer. (A simple example might be a variable rename by Left and some added lines using that variable by Right. The merge will probably have an unresolved symbol. Alternatively, this might introduce a semantic conflict by variable hiding.)
Finally, a semantic conflict is not flagged by the VCS, the result compiles, but the code may have problems running. In mild cases, incorrect results are produced. In severe cases, a crash could be introduced. Even these should be detected before commit by a very careful programmer, through either code review or unit testing.
My example of a semantic conflict uses SVN (Subversion) and C++, but those choices are not really relevant to the essence of the question.
The base code is:
int i = 0;
int odds = 0;
while (i < 10)
{
if ((i & 1) != 0)
{
odds *= 10;
odds += i;
}
// next
++ i;
}
assert (odds == 13579)
The Left (L
) and Right (R
) changes are as follows.
Left's 'optimisation' (changing the values the loop variable takes):
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)
Right's 'optimisation' (changing how the loop variable is used):
int i = 0;
int odds = 0;
while (i < 5) // R
{
odds *= 10;
odds += 2 * i + 1; // R
// next
++ i;
}
assert (odds == 13579)
This is the result of a merge or update, and is not detected by SVN (which is correct behaviour for the VCS), so it is not a textual conflict. Note that it compiles, so it is not a syntactic conflict.
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)
The assert
fails because odds
is 37.
So my question is as follows. Is there a simpler example than this? Is there a simple example where the compiled executable has a new crash?
As a secondary question, are there cases of this that you have encountered in real code? Again, simple examples are especially welcome.