I just can't understand how such a situation could be created. I have attempted to recreate this criss-cross merge situation between branches using a test repository but I cannot replicate it. In all cases, I always wind up with 1 merge commit to which both A and B point to (instead of A and B pointing to independent merge commits as the diagram illustrates).
Can anyone illustrate how this situation can arise?
Criss-cross merges can arise in different ways. On example that springs to mind is when you have two branch references pointing to the same merge commit (one of those branches being checked out) and you run git commit --amend
. The following toy example does just that:
# set things up
cd ~/Desktop
mkdir crisscross
cd crisscross
git init
# make an initial commit
printf "bar\n" > README.md
git add README.md
git commit -m "add README"
# add a line at the top of the file and commit
sed -i '' '1s/^/foo\n/' README.md
git commit -am "add foo line"
# create and checkout a branch pointing at the initial commit
git checkout -b other master^
# add a line at the bottom of the file and commit
printf "baz\n" >> README.md
git commit -am "add baz line"
# do a merge and make both branches point to this merge commit
git merge master
git checkout master
git merge other
At this stage, the output of git log --graph --oneline --decorate --all
is
* 30b9175 (HEAD, master, other) Merge branch 'master' into other
|\
| * f318ead add foo line
* | 31875d9 add baz line
|/
* 8b313a0 add README
Now amend the last commit (see How does git commit --amend work, exactly? for more details):
git commit --amend
After that, the output of git log --graph --oneline --decorate --all
will be
* 69bbcbe (HEAD, master) Amended merge commit
|\
| | * 30b9175 (other) Merge branch 'master' into other
| | |\
| |/ /
|/| /
| |/
| * f318ead add foo line
* | 31875d9 add baz line
|/
* 8b313a0 add README
There you go: the history now contains criss-cross merges.
Is this a common situation or an error situation?
As illustrated above, the situation can arise. It may be undesirable, but it shouldn't be considered an "error state".