git-merge-base
Find the best common ancestor for merging
TLDR
Print the best common ancestor of two commits
Print all best common ancestors of two commits
Check if a commit is an ancestor of a specific commit
SYNOPSIS
git merge-base [--all] commit commit...
git merge-base --octopus commit...
git merge-base --independent commit...
git merge-base --is-ancestor commit commit
git merge-base --fork-point rev [rev]
PARAMETERS
--all
Output all common ancestors, not just the best one. This can result in multiple lines of output.
--octopus
Find a common merge base for an N-way merge (octopus merge). This finds the common ancestor of all specified commits and reports the best ones that are not ancestors of each other.
--independent
Identify independent commit chains that are not ancestors of each other. These are typically the tips of merge bases found by --octopus mode when multiple independent merge bases exist.
--is-ancestor
Check if the first commit is an ancestor of the second commit. Exits with 0 status code if true, 1 otherwise. No output is produced.
--fork-point
Find a common ancestor using the reflog to approximate where a branch diverged from another. This is useful for rebasing a series of private commits that were originally based on an upstream branch, even if the upstream branch has been rebased itself.
DESCRIPTION
The git merge-base command helps in finding a good common ancestor between two or more commits. It's primarily used internally by git merge and git rebase to determine the common point from which changes diverged. For a standard two-branch merge (git merge A B), git merge-base A B typically finds the single common ancestor. This ancestor is crucial for performing a 3-way merge, where changes from both branches are applied relative to this common base.
When there are multiple common ancestors, git merge-base intelligently selects the "best" common ancestor, usually the one that is an ancestor of all other common ancestors. This ensures that the merge is based on the most recent shared history. The command also supports modes for finding common ancestors for N-way merges (--octopus), identifying independent heads (--independent), and checking ancestry relationships (--is-ancestor). Understanding git merge-base is key to grasping how Git handles branching and merging operations internally.
CAVEATS
In scenarios with complex histories like "criss-cross merges" (where two branches merge and then one of the merged branches merges back into the other, creating diamond shapes in the history), there might be multiple "best" common ancestors. git merge-base attempts to find the most appropriate one but its choice might not always be what a human intuitively expects in highly convoluted graphs. When given more than two commits without --octopus or --independent, it finds a common ancestor of all of them, which can also lead to less intuitive results in specific graph configurations compared to a simple two-commit merge base.
BEST COMMON ANCESTOR
When multiple common ancestors exist between two commits, git merge-base selects the 'best' one. This 'best' ancestor is defined as the unique common ancestor that is an ancestor of all other common ancestors. This ensures that the merge base is the most recent shared point in the history that precedes both branches, minimizing the set of changes that need to be merged.
USAGE WITH MULTIPLE COMMITS
When git merge-base is given more than two commits without the --octopus or --independent options, it finds a common ancestor of all of them. This is internally handled by computing the merge base of the first two commits, then finding the merge base of that result with the third commit, and so on. This process aims to identify a single point in history that precedes all specified branches.
HISTORY
The git merge-base command is a fundamental "plumbing" utility within Git's architecture, designed to find common ancestors. It has been a core component since the early days of Git, forming the basis for higher-level commands like git merge and git rebase. Its various modes (--octopus, --independent, --is-ancestor) have been added over time to address increasingly complex merging scenarios and to provide more granular control over ancestry queries.
SEE ALSO
git-merge(1), git-rebase(1), git-log(1)