3

When I merge between branches, git does a recursive merge with conflicts, putting in <<<<<<< Temporary merge branch x blocks.

I abort the merge, and then do git merge-base <source-commit> <target-commit>, but it returns only one SHA1.

Is it possible to find out what the multiple base commits are?

Lee
  • 1,591
  • 1
  • 14
  • 28

2 Answers2

4

You want the --all option to git-merge-base. From the documentation:

-a, --all
    Output all merge bases for the commits, instead of just one.

This will show all the merge bases that will be used to create a temporary tree as a recursive merge base.

For example, consider some branches 'A' and 'B' that were criss-cross merged:

       3a4f5a6 -- 973b703 -- a34e5a1 (branch A)
      /        \ /
7c7bf85         X
      \        / \
       8f35f30 -- 3fd4180 -- 723181f (branch B)

It's clear that branches A and B have two common ancestors that were involved in a criss-cross merge: 3a3f5a6 and 8f35f30. git-merge-base will choose one of the common ancestors as a merge base, but using the --all flag will include both:

% git-merge-base A B
3a3f5a6ec1c968d1d2d5d20dee0d161a4351f279
% git-merge-base --all A B
3a3f5a6ec1c968d1d2d5d20dee0d161a4351f279
8f35f30bfe09513f96cf8aa4df0834ae34e93bae

In this situation, as you note, git-merge-recursive would merge the two merge base to create a virtual commit that will be used as the actual common ancestor for the three-way merge algorithm.

Edward Thomson
  • 74,857
  • 14
  • 158
  • 187
  • Perfect, I missed seeing that in the docs, I'll give that a go. In your comments it seems you said 973b703 and 3fd4180 are the common ancestors. Are they not 3a4f5a6 and 8f35f30? – Lee May 05 '16 at 14:46
  • Hah, yes, pardon me. My writeup was incorrect, I evidently couldn't read the graph *or* the tool's output below. Edited. – Edward Thomson May 05 '16 at 16:11
  • 2
    In the ideal case, all merge bases have identical trees and the intermediate merge product is the same as any of its inputs. In practice, occasionally not, as you (OP) found! :-) One other note, a while back I checked the code for merge-recursive: if there are three or more merge bases, the process is actually iterative on those bases. That is, merge first gets the `--all` list, then merges the first two of those, then repeatedly merges each additional entry into the merge result. – torek May 05 '16 at 16:58
  • That's exactly right. And... when merging your merge bases _those_ could have been criss-cross merged. So your merge bases may need a virtual merge base... It's recursive merging all the way down. :) – Edward Thomson May 05 '16 at 17:07
0

For a note on how to re-do the merge of one specific file using one specific base, see this answer to your related question. [Historical note: the OP deleted the question, but has now resurrected it; I had the answer here but it belongs there; hence all these links....]

Community
  • 1
  • 1
torek
  • 448,244
  • 59
  • 642
  • 775
  • Thanks for your time, I've undeleted the question you're referring to, feel free to move this answer over :) http://stackoverflow.com/questions/37049055/git-choose-simpler-base-in-recursive-merge – Lee May 06 '16 at 14:00