Home Explore Blog CI



git

2nd chunk of `Documentation/git-merge-base.adoc`
8c75facaaf42dbc9c49ee2ed27e39adab4b5f4a92e19b0290000000100000986
 merge base between 'A' and 'B' is '1'.

Given three commits 'A', 'B', and 'C', `git merge-base A B C` will compute the
merge base between 'A' and a hypothetical commit 'M', which is a merge
between 'B' and 'C'.  For example, with this topology:

....
       o---o---o---o---C
      /
     /   o---o---o---B
    /   /
---2---1---o---o---o---A
....

the result of `git merge-base A B C` is '1'.  This is because the
equivalent topology with a merge commit 'M' between 'B' and 'C' is:


....
       o---o---o---o---o
      /                 \
     /   o---o---o---o---M
    /   /
---2---1---o---o---o---A
....

and the result of `git merge-base A M` is '1'.  Commit '2' is also a
common ancestor between 'A' and 'M', but '1' is a better common ancestor,
because '2' is an ancestor of '1'.  Hence, '2' is not a merge base.

The result of `git merge-base --octopus A B C` is '2', because '2' is
the best common ancestor of all commits.

When the history involves criss-cross merges, there can be more than one
'best' common ancestor for two commits.  For example, with this topology:

....
---1---o---A
    \ /
     X
    / \
---2---o---o---B
....

both '1' and '2' are merge bases of A and B.  Neither one is better than
the other (both are 'best' merge bases).  When the `--all` option is not given,
it is unspecified which best one is output.

A common idiom to check "fast-forward-ness" between two commits A
and B is (or at least used to be) to compute the merge base between
A and B, and check if it is the same as A, in which case, A is an
ancestor of B.  You will see this idiom used often in older scripts.

....
A=$(git rev-parse --verify A)
if test "$A" = "$(git merge-base A B)"
then
	... A is an ancestor of B ...
fi
....

In modern git, you can say this in a more direct way:

....
if git merge-base --is-ancestor A B
then
	... A is an ancestor of B ...
fi
....

instead.

Discussion on fork-point mode
-----------------------------

After working on the `topic` branch created with `git switch -c
topic origin/master`, the history of remote-tracking branch
`origin/master` may have been rewound and rebuilt, leading to a
history of this shape:

....
		 o---B2
		/
---o---o---B1--o---o---o---B (origin/master)
	\
	 B0
	  \
	   D0---D1---D (topic)
....

where `origin/master` used to point at commits B0, B1, B2 and now it
points at B, and your `topic` branch was started on top of it back
when `origin/master` was at B0, and you

Title: Git Merge Base Scenarios and Options
Summary
The git-merge-base command handles various merge scenarios, including simple two-commit merges, octopus merges, and histories with criss-cross merges, and provides options like --all, --octopus, and --is-ancestor to control the output and behavior, with applications in scripts to check fast-forward-ness and ancestor relationships between commits.