Documentation / git-merge-base.txton commit graph: add commit graph design document (ae30d7b)
   1git-merge-base(1)
   2=================
   3
   4NAME
   5----
   6git-merge-base - Find as good common ancestors as possible for a merge
   7
   8
   9SYNOPSIS
  10--------
  11[verse]
  12'git merge-base' [-a|--all] <commit> <commit>...
  13'git merge-base' [-a|--all] --octopus <commit>...
  14'git merge-base' --is-ancestor <commit> <commit>
  15'git merge-base' --independent <commit>...
  16'git merge-base' --fork-point <ref> [<commit>]
  17
  18DESCRIPTION
  19-----------
  20
  21'git merge-base' finds best common ancestor(s) between two commits to use
  22in a three-way merge.  One common ancestor is 'better' than another common
  23ancestor if the latter is an ancestor of the former.  A common ancestor
  24that does not have any better common ancestor is a 'best common
  25ancestor', i.e. a 'merge base'.  Note that there can be more than one
  26merge base for a pair of commits.
  27
  28OPERATION MODES
  29---------------
  30
  31As the most common special case, specifying only two commits on the
  32command line means computing the merge base between the given two commits.
  33
  34More generally, among the two commits to compute the merge base from,
  35one is specified by the first commit argument on the command line;
  36the other commit is a (possibly hypothetical) commit that is a merge
  37across all the remaining commits on the command line.
  38
  39As a consequence, the 'merge base' is not necessarily contained in each of the
  40commit arguments if more than two commits are specified. This is different
  41from linkgit:git-show-branch[1] when used with the `--merge-base` option.
  42
  43--octopus::
  44        Compute the best common ancestors of all supplied commits,
  45        in preparation for an n-way merge.  This mimics the behavior
  46        of 'git show-branch --merge-base'.
  47
  48--independent::
  49        Instead of printing merge bases, print a minimal subset of
  50        the supplied commits with the same ancestors.  In other words,
  51        among the commits given, list those which cannot be reached
  52        from any other.  This mimics the behavior of 'git show-branch
  53        --independent'.
  54
  55--is-ancestor::
  56        Check if the first <commit> is an ancestor of the second <commit>,
  57        and exit with status 0 if true, or with status 1 if not.
  58        Errors are signaled by a non-zero status that is not 1.
  59
  60--fork-point::
  61        Find the point at which a branch (or any history that leads
  62        to <commit>) forked from another branch (or any reference)
  63        <ref>. This does not just look for the common ancestor of
  64        the two commits, but also takes into account the reflog of
  65        <ref> to see if the history leading to <commit> forked from
  66        an earlier incarnation of the branch <ref> (see discussion
  67        on this mode below).
  68
  69OPTIONS
  70-------
  71-a::
  72--all::
  73        Output all merge bases for the commits, instead of just one.
  74
  75DISCUSSION
  76----------
  77
  78Given two commits 'A' and 'B', `git merge-base A B` will output a commit
  79which is reachable from both 'A' and 'B' through the parent relationship.
  80
  81For example, with this topology:
  82
  83                 o---o---o---B
  84                /
  85        ---o---1---o---o---o---A
  86
  87the merge base between 'A' and 'B' is '1'.
  88
  89Given three commits 'A', 'B' and 'C', `git merge-base A B C` will compute the
  90merge base between 'A' and a hypothetical commit 'M', which is a merge
  91between 'B' and 'C'.  For example, with this topology:
  92
  93               o---o---o---o---C
  94              /
  95             /   o---o---o---B
  96            /   /
  97        ---2---1---o---o---o---A
  98
  99the result of `git merge-base A B C` is '1'.  This is because the
 100equivalent topology with a merge commit 'M' between 'B' and 'C' is:
 101
 102
 103               o---o---o---o---o
 104              /                 \
 105             /   o---o---o---o---M
 106            /   /
 107        ---2---1---o---o---o---A
 108
 109and the result of `git merge-base A M` is '1'.  Commit '2' is also a
 110common ancestor between 'A' and 'M', but '1' is a better common ancestor,
 111because '2' is an ancestor of '1'.  Hence, '2' is not a merge base.
 112
 113The result of `git merge-base --octopus A B C` is '2', because '2' is
 114the best common ancestor of all commits.
 115
 116When the history involves criss-cross merges, there can be more than one
 117'best' common ancestor for two commits.  For example, with this topology:
 118
 119        ---1---o---A
 120            \ /
 121             X
 122            / \
 123        ---2---o---o---B
 124
 125both '1' and '2' are merge-bases of A and B.  Neither one is better than
 126the other (both are 'best' merge bases).  When the `--all` option is not given,
 127it is unspecified which best one is output.
 128
 129A common idiom to check "fast-forward-ness" between two commits A
 130and B is (or at least used to be) to compute the merge base between
 131A and B, and check if it is the same as A, in which case, A is an
 132ancestor of B.  You will see this idiom used often in older scripts.
 133
 134        A=$(git rev-parse --verify A)
 135        if test "$A" = "$(git merge-base A B)"
 136        then
 137                ... A is an ancestor of B ...
 138        fi
 139
 140In modern git, you can say this in a more direct way:
 141
 142        if git merge-base --is-ancestor A B
 143        then
 144                ... A is an ancestor of B ...
 145        fi
 146
 147instead.
 148
 149Discussion on fork-point mode
 150-----------------------------
 151
 152After working on the `topic` branch created with `git checkout -b
 153topic origin/master`, the history of remote-tracking branch
 154`origin/master` may have been rewound and rebuilt, leading to a
 155history of this shape:
 156
 157                         o---B2
 158                        /
 159        ---o---o---B1--o---o---o---B (origin/master)
 160                \
 161                 B0
 162                  \
 163                   D0---D1---D (topic)
 164
 165where `origin/master` used to point at commits B0, B1, B2 and now it
 166points at B, and your `topic` branch was started on top of it back
 167when `origin/master` was at B0, and you built three commits, D0, D1,
 168and D, on top of it.  Imagine that you now want to rebase the work
 169you did on the topic on top of the updated origin/master.
 170
 171In such a case, `git merge-base origin/master topic` would return the
 172parent of B0 in the above picture, but B0^..D is *not* the range of
 173commits you would want to replay on top of B (it includes B0, which
 174is not what you wrote; it is a commit the other side discarded when
 175it moved its tip from B0 to B1).
 176
 177`git merge-base --fork-point origin/master topic` is designed to
 178help in such a case.  It takes not only B but also B0, B1, and B2
 179(i.e. old tips of the remote-tracking branches your repository's
 180reflog knows about) into account to see on which commit your topic
 181branch was built and finds B0, allowing you to replay only the
 182commits on your topic, excluding the commits the other side later
 183discarded.
 184
 185Hence
 186
 187    $ fork_point=$(git merge-base --fork-point origin/master topic)
 188
 189will find B0, and
 190
 191    $ git rebase --onto origin/master $fork_point topic
 192
 193will replay D0, D1 and D on top of B to create a new history of this
 194shape:
 195
 196                         o---B2
 197                        /
 198        ---o---o---B1--o---o---o---B (origin/master)
 199                \                   \
 200                 B0                  D0'--D1'--D' (topic - updated)
 201                  \
 202                   D0---D1---D (topic - old)
 203
 204A caveat is that older reflog entries in your repository may be
 205expired by `git gc`.  If B0 no longer appears in the reflog of the
 206remote-tracking branch `origin/master`, the `--fork-point` mode
 207obviously cannot find it and fails, avoiding to give a random and
 208useless result (such as the parent of B0, like the same command
 209without the `--fork-point` option gives).
 210
 211Also, the remote-tracking branch you use the `--fork-point` mode
 212with must be the one your topic forked from its tip.  If you forked
 213from an older commit than the tip, this mode would not find the fork
 214point (imagine in the above sample history B0 did not exist,
 215origin/master started at B1, moved to B2 and then B, and you forked
 216your topic at origin/master^ when origin/master was B1; the shape of
 217the history would be the same as above, without B0, and the parent
 218of B1 is what `git merge-base origin/master topic` correctly finds,
 219but the `--fork-point` mode will not, because it is not one of the
 220commits that used to be at the tip of origin/master).
 221
 222
 223See also
 224--------
 225linkgit:git-rev-list[1],
 226linkgit:git-show-branch[1],
 227linkgit:git-merge[1]
 228
 229GIT
 230---
 231Part of the linkgit:git[1] suite