git merge-base returns the best common ancestor of two commits - the point your branch diverged.
merge-base is how CI computes "changed in this PR": diff against the merge base of the branch and its target.
What it does
git merge-base finds the commit where two branches diverged (their best common ancestor), which is the correct base for computing a pull request’s effective diff.
Common usage
Terminal
git merge-base main feature
git diff $(git merge-base main HEAD) HEAD # PR changes only
git merge-base --is-ancestor A B && echo "A is ancestor of B"
git merge-base --fork-point main feature
Options
Flag
What it does
--is-ancestor
Exit 0 if first commit is an ancestor of second
--fork-point
Use reflog to find where a branch forked
--all
Print all merge bases (for criss-cross merges)
--octopus
Best common ancestor of many commits
Common errors in CI
fatal: Not a valid commit name or an empty result usually means the base branch is missing on the runner - a shallow or single-branch clone. Fetch the target branch (git fetch origin main) or set fetch-depth: 0 so the common ancestor is reachable.
Using this in CI
CI checkouts are shallow and detached by default, which changes the answer this command gives you. Commands that read history, branch names, or tags need the checkout configured for it.
.github/workflows/ci.yml
- uses:actions/checkout@v4with:fetch-depth:0 # history, tags, and git describe all need this- run:|git rev-parse --is-shallow-repository # expect falsegit rev-parse --abbrev-ref HEAD # prints HEAD when detached
Frequently asked questions
git merge-base: Usage, Options & Common CI Errors?
merge-base is how CI computes "changed in this PR": diff against the merge base of the branch and its target.
What it does?
git merge-base finds the commit where two branches diverged (their best common ancestor), which is the correct base for computing a pull request’s effective diff.
Common errors in CI?
fatal: Not a valid commit name or an empty result usually means the base branch is missing on the runner - a shallow or single-branch clone. Fetch the target branch (git fetch origin main) or set fetch-depth: 0 so the common ancestor is reachable.