After many trials, I got this simple test case scenario:
a --> b --> c -- (master)
\\ \\
--> d --> b\' --> e (branch)
<
The basic problem is that there is no formal model for what it means to do correct automated merges that do the right thing in every case. In fact, "the right thing" can differ for different use cases in ways which the merge algorithm has no idea about. There have been a variety of attempts to come up with a single, correct merge algorithm that always does the right thing (various Monotone merge strategies, Codeville, Precise Codeville, Darcs, and so on), and all of them fail in some way in real-world use cases.
So, for a real-world merge algorithm "it works pretty well on a real codebase with lots of merges" is about the best you're going to be able to do. This means that you should never blindly trust the outcome of a clean automated merge; while it may have merged cleanly without conflicts, that may not have done exactly what you expected. You still need to review what the merge did, and test the result.
My general approach is to try a couple of different merge options, like you did, to see if one of them produces the correct merge. If that doesn't work to get you the correct merge (or a merge that produces the appropriate conflict that you can resolve), then you should do git merge --no-commit
, and fix up the merge as appropriate before committing it.