We recently went through some merge issues with git, and while it probably did 'The Right Thing'(TM) it wasn't what I expected. I have reduced an issue to a small public github repository located at https://github.com/geretz/merge-quirk.
quirk.c exists on master. merge-src and merge-dst are both branched from the same version on master, which is the common ancestor for the eventual merge. merge-src adds a comment and some code. merge-dst reformats the code and changes the exiting comments but does not have the added comment or code.
git merge detects and declares a conflict.
git clone https://github.com/geretz/merge-quirk.git
cd merge-quirk
git checkout merge-dst
git merge origin/merge-src
Auto-merging quirk.c
CONFLICT (content): Merge conflict in quirk.c
Automatic merge failed; fix conflicts and then commit the result.
However the thisLineMightDisapper (sic) function call will get lost if a naive/trusting developer chooses the origin/merge-src code block in the conflict flagged quirk.c .
In my mental model, if the thisLineMightDisapper function call exists in both HEAD and origin/src in conflicting states it should exist in both of the conflict blocks, if it doesn't exist in conflicting states it should exist outside of both conflict blocks. Why does it appear only inside the HEAD block ?
<<<<<<< HEAD
// a few comment lines - change 1
// that existed - change 2
// in the common ancestor - change 3
// that get changed - change 4
if(1)
{
if (f(1, 2))
{
if (thisLineMightDisapper(42))
=======
// a few comment lines
// that existed
// in the common ancestor
// added this line in merge-src branch
// that get changed
if(1) {
if (f(1, 2))
>>>>>>> origin/merge-src
{
t = time(0);
}
}
}
if (anotherFunction(1,2))
{
t = time(0)
f(0);
}
}
The files
master/quirk.c
// a few comment lines
// that existed
// in the common ancestor
// that get changed
if(1) {
if (f(1, 2))
{
if (thisLineMightDisapper(42)) {
t = time(0);
}
}
}
}
merge-src/quirk.c
// a few comment lines
// that existed
// in the common ancestor
// added this line in merge-src branch
// that get changed
if(1) {
if (f(1, 2))
{
if (thisLineMightDisapper(42)) {
t = time(0);
}
}
}
if (anotherFunction(1,2))
{
t = time(0)
f(0);
}
}
merge-dst/quirk.c
// a few comment lines - change 1
// that existed - change 2
// in the common ancestor - change 3
// that get changed - change 4
if(1)
{
if (f(1, 2))
{
if (thisLineMightDisapper(42))
{
t = time(0);
}
}
}
}