How merge and rebase decide what's new on each side.
Find the best common ancestor between commits. This is the commit merge uses as its base and rebase uses to decide which patches are 'yours'.
History is a DAG; merge-base walks back from each input until it finds the youngest commit reachable from all of them. Get the base wrong and merges/rebases produce nonsense.
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 <ref> [<commit>]| Flag | What it does |
|---|---|
<commit>... | Two or more commits to find an ancestor for. |
--all | Print every best common ancestor, not just one (criss-cross history). |
--octopus | Compute a single base suitable for an N-way octopus merge. |
--independent | Reduce a list to those commits not reachable from the others. |
--is-ancestor <a> <b> | Exit 0 if <a> is an ancestor of <b>; for scripts, no output. |
--fork-point <ref> [<commit>] | Use the reflog of <ref> to find the point you originally branched from, even if <ref> was rewritten. |
git diff $(git merge-base main HEAD) HEAD.--is-ancestor).--fork-point.--independent.git merge-base main featuregit merge-base --is-ancestor abc1234 release/2.0 && echo yesgit merge-base --fork-point origin/maingit merge-base --all topic1 topic2--is-ancestor, check $? directly; do not parse stdout, there is none.--fork-point for git rebase after upstream force-pushes; otherwise you'll replay commits that no longer belong to you.--all you get just one and may misread history.--fork-point depends on the local reflog of the upstream ref; on a fresh clone it may have nothing useful to work with.Hit each option, then Check answers. Score is recorded; Next is always open.