David Greaves | 2cf565c | 2005-05-10 22:32:30 +0100 | [diff] [blame] | 1 | git-merge-base(1) |
| 2 | ================= |
David Greaves | 2cf565c | 2005-05-10 22:32:30 +0100 | [diff] [blame] | 3 | |
| 4 | NAME |
| 5 | ---- |
Junio C Hamano | c3f0baa | 2007-01-18 15:53:37 -0800 | [diff] [blame] | 6 | git-merge-base - Find as good common ancestors as possible for a merge |
David Greaves | 2cf565c | 2005-05-10 22:32:30 +0100 | [diff] [blame] | 7 | |
| 8 | |
| 9 | SYNOPSIS |
| 10 | -------- |
Jonathan Nieder | a1e0ad7 | 2010-08-17 02:01:54 -0500 | [diff] [blame] | 11 | [verse] |
Ævar Arnfjörð Bjarmason | e2f4e7e | 2022-10-13 17:39:06 +0200 | [diff] [blame] | 12 | 'git merge-base' [-a | --all] <commit> <commit>... |
| 13 | 'git merge-base' [-a | --all] --octopus <commit>... |
Junio C Hamano | 5907cda | 2012-08-30 14:52:20 -0700 | [diff] [blame] | 14 | 'git merge-base' --is-ancestor <commit> <commit> |
Jonathan Nieder | a1e0ad7 | 2010-08-17 02:01:54 -0500 | [diff] [blame] | 15 | 'git merge-base' --independent <commit>... |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 16 | 'git merge-base' --fork-point <ref> [<commit>] |
David Greaves | 2cf565c | 2005-05-10 22:32:30 +0100 | [diff] [blame] | 17 | |
| 18 | DESCRIPTION |
| 19 | ----------- |
Fredrik Kuivinen | 2aa8396 | 2006-05-16 07:58:15 +0200 | [diff] [blame] | 20 | |
Elijah Newren | 0a4f051 | 2023-10-08 06:45:17 +0000 | [diff] [blame] | 21 | 'git merge-base' finds the best common ancestor(s) between two commits to use |
Junio C Hamano | 99f1c04 | 2008-07-30 07:04:43 +0200 | [diff] [blame] | 22 | in a three-way merge. One common ancestor is 'better' than another common |
| 23 | ancestor if the latter is an ancestor of the former. A common ancestor |
Ralf Wildenhues | 29b802a | 2008-12-09 07:23:51 +0100 | [diff] [blame] | 24 | that does not have any better common ancestor is a 'best common |
Junio C Hamano | 99f1c04 | 2008-07-30 07:04:43 +0200 | [diff] [blame] | 25 | ancestor', i.e. a 'merge base'. Note that there can be more than one |
Ralf Wildenhues | 29b802a | 2008-12-09 07:23:51 +0100 | [diff] [blame] | 26 | merge base for a pair of commits. |
Fredrik Kuivinen | 2aa8396 | 2006-05-16 07:58:15 +0200 | [diff] [blame] | 27 | |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 28 | OPERATION MODES |
| 29 | --------------- |
Jonathan Nieder | ded7e04 | 2011-04-15 10:38:55 +0200 | [diff] [blame] | 30 | |
Elijah Newren | 9a9fd28 | 2023-10-08 06:45:20 +0000 | [diff] [blame] | 31 | In the most common special case, specifying only two commits on the |
Jonathan Nieder | ded7e04 | 2011-04-15 10:38:55 +0200 | [diff] [blame] | 32 | command line means computing the merge base between the given two commits. |
| 33 | |
| 34 | More generally, among the two commits to compute the merge base from, |
| 35 | one is specified by the first commit argument on the command line; |
| 36 | the other commit is a (possibly hypothetical) commit that is a merge |
| 37 | across all the remaining commits on the command line. |
David Greaves | 2cf565c | 2005-05-10 22:32:30 +0100 | [diff] [blame] | 38 | |
Michael J Gruber | f621a84 | 2009-08-05 09:59:20 +0200 | [diff] [blame] | 39 | As a consequence, the 'merge base' is not necessarily contained in each of the |
| 40 | commit arguments if more than two commits are specified. This is different |
| 41 | from linkgit:git-show-branch[1] when used with the `--merge-base` option. |
| 42 | |
Jonathan Nieder | aa8f98c | 2010-08-17 02:01:15 -0500 | [diff] [blame] | 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 | |
Jonathan Nieder | a1e0ad7 | 2010-08-17 02:01:54 -0500 | [diff] [blame] | 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 | |
Junio C Hamano | 5907cda | 2012-08-30 14:52:20 -0700 | [diff] [blame] | 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 | |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 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 |
Elijah Newren | 9a9fd28 | 2023-10-08 06:45:20 +0000 | [diff] [blame] | 67 | of this mode below). |
Junio C Hamano | 5907cda | 2012-08-30 14:52:20 -0700 | [diff] [blame] | 68 | |
Jonathan Nieder | ded7e04 | 2011-04-15 10:38:55 +0200 | [diff] [blame] | 69 | OPTIONS |
| 70 | ------- |
| 71 | -a:: |
| 72 | --all:: |
| 73 | Output all merge bases for the commits, instead of just one. |
| 74 | |
Junio C Hamano | 99f1c04 | 2008-07-30 07:04:43 +0200 | [diff] [blame] | 75 | DISCUSSION |
| 76 | ---------- |
| 77 | |
| 78 | Given two commits 'A' and 'B', `git merge-base A B` will output a commit |
| 79 | which is reachable from both 'A' and 'B' through the parent relationship. |
| 80 | |
| 81 | For example, with this topology: |
| 82 | |
Martin Ågren | 922a2c9 | 2019-09-07 16:12:48 +0200 | [diff] [blame] | 83 | .... |
| 84 | o---o---o---B |
| 85 | / |
| 86 | ---o---1---o---o---o---A |
| 87 | .... |
Junio C Hamano | 99f1c04 | 2008-07-30 07:04:43 +0200 | [diff] [blame] | 88 | |
| 89 | the merge base between 'A' and 'B' is '1'. |
| 90 | |
Elijah Newren | 4d54268 | 2023-10-08 06:45:24 +0000 | [diff] [blame] | 91 | Given three commits 'A', 'B', and 'C', `git merge-base A B C` will compute the |
Ralf Wildenhues | 29b802a | 2008-12-09 07:23:51 +0100 | [diff] [blame] | 92 | merge base between 'A' and a hypothetical commit 'M', which is a merge |
Junio C Hamano | 99f1c04 | 2008-07-30 07:04:43 +0200 | [diff] [blame] | 93 | between 'B' and 'C'. For example, with this topology: |
| 94 | |
Martin Ågren | 922a2c9 | 2019-09-07 16:12:48 +0200 | [diff] [blame] | 95 | .... |
| 96 | o---o---o---o---C |
| 97 | / |
| 98 | / o---o---o---B |
| 99 | / / |
| 100 | ---2---1---o---o---o---A |
| 101 | .... |
Junio C Hamano | 99f1c04 | 2008-07-30 07:04:43 +0200 | [diff] [blame] | 102 | |
| 103 | the result of `git merge-base A B C` is '1'. This is because the |
| 104 | equivalent topology with a merge commit 'M' between 'B' and 'C' is: |
| 105 | |
| 106 | |
Martin Ågren | 922a2c9 | 2019-09-07 16:12:48 +0200 | [diff] [blame] | 107 | .... |
| 108 | o---o---o---o---o |
| 109 | / \ |
| 110 | / o---o---o---o---M |
| 111 | / / |
| 112 | ---2---1---o---o---o---A |
| 113 | .... |
Junio C Hamano | 99f1c04 | 2008-07-30 07:04:43 +0200 | [diff] [blame] | 114 | |
| 115 | and the result of `git merge-base A M` is '1'. Commit '2' is also a |
| 116 | common ancestor between 'A' and 'M', but '1' is a better common ancestor, |
| 117 | because '2' is an ancestor of '1'. Hence, '2' is not a merge base. |
| 118 | |
Vincent van Ravesteijn | 5729482 | 2011-04-15 10:34:03 +0200 | [diff] [blame] | 119 | The result of `git merge-base --octopus A B C` is '2', because '2' is |
| 120 | the best common ancestor of all commits. |
| 121 | |
Junio C Hamano | 99f1c04 | 2008-07-30 07:04:43 +0200 | [diff] [blame] | 122 | When the history involves criss-cross merges, there can be more than one |
Ralf Wildenhues | 29b802a | 2008-12-09 07:23:51 +0100 | [diff] [blame] | 123 | 'best' common ancestor for two commits. For example, with this topology: |
Junio C Hamano | 99f1c04 | 2008-07-30 07:04:43 +0200 | [diff] [blame] | 124 | |
Martin Ågren | 922a2c9 | 2019-09-07 16:12:48 +0200 | [diff] [blame] | 125 | .... |
| 126 | ---1---o---A |
| 127 | \ / |
| 128 | X |
| 129 | / \ |
| 130 | ---2---o---o---B |
| 131 | .... |
Junio C Hamano | 99f1c04 | 2008-07-30 07:04:43 +0200 | [diff] [blame] | 132 | |
Elijah Newren | f22fdf3 | 2023-10-08 06:45:18 +0000 | [diff] [blame] | 133 | both '1' and '2' are merge bases of A and B. Neither one is better than |
Ralf Wildenhues | 29b802a | 2008-12-09 07:23:51 +0100 | [diff] [blame] | 134 | the other (both are 'best' merge bases). When the `--all` option is not given, |
Junio C Hamano | 99f1c04 | 2008-07-30 07:04:43 +0200 | [diff] [blame] | 135 | it is unspecified which best one is output. |
David Greaves | 2cf565c | 2005-05-10 22:32:30 +0100 | [diff] [blame] | 136 | |
Junio C Hamano | 5907cda | 2012-08-30 14:52:20 -0700 | [diff] [blame] | 137 | A common idiom to check "fast-forward-ness" between two commits A |
| 138 | and B is (or at least used to be) to compute the merge base between |
| 139 | A and B, and check if it is the same as A, in which case, A is an |
| 140 | ancestor of B. You will see this idiom used often in older scripts. |
| 141 | |
Martin Ågren | 922a2c9 | 2019-09-07 16:12:48 +0200 | [diff] [blame] | 142 | .... |
| 143 | A=$(git rev-parse --verify A) |
| 144 | if test "$A" = "$(git merge-base A B)" |
| 145 | then |
| 146 | ... A is an ancestor of B ... |
| 147 | fi |
| 148 | .... |
Junio C Hamano | 5907cda | 2012-08-30 14:52:20 -0700 | [diff] [blame] | 149 | |
| 150 | In modern git, you can say this in a more direct way: |
| 151 | |
Martin Ågren | 922a2c9 | 2019-09-07 16:12:48 +0200 | [diff] [blame] | 152 | .... |
| 153 | if git merge-base --is-ancestor A B |
| 154 | then |
| 155 | ... A is an ancestor of B ... |
| 156 | fi |
| 157 | .... |
Junio C Hamano | 5907cda | 2012-08-30 14:52:20 -0700 | [diff] [blame] | 158 | |
| 159 | instead. |
| 160 | |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 161 | Discussion on fork-point mode |
| 162 | ----------------------------- |
| 163 | |
Nguyễn Thái Ngọc Duy | 328c6cb | 2019-03-29 17:39:19 +0700 | [diff] [blame] | 164 | After working on the `topic` branch created with `git switch -c |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 165 | topic origin/master`, the history of remote-tracking branch |
| 166 | `origin/master` may have been rewound and rebuilt, leading to a |
| 167 | history of this shape: |
| 168 | |
Martin Ågren | 922a2c9 | 2019-09-07 16:12:48 +0200 | [diff] [blame] | 169 | .... |
| 170 | o---B2 |
| 171 | / |
| 172 | ---o---o---B1--o---o---o---B (origin/master) |
| 173 | \ |
| 174 | B0 |
| 175 | \ |
| 176 | D0---D1---D (topic) |
| 177 | .... |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 178 | |
Junio C Hamano | 6d1700b | 2017-11-09 11:49:45 +0900 | [diff] [blame] | 179 | where `origin/master` used to point at commits B0, B1, B2 and now it |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 180 | points at B, and your `topic` branch was started on top of it back |
Junio C Hamano | 6d1700b | 2017-11-09 11:49:45 +0900 | [diff] [blame] | 181 | when `origin/master` was at B0, and you built three commits, D0, D1, |
| 182 | and D, on top of it. Imagine that you now want to rebase the work |
| 183 | you did on the topic on top of the updated origin/master. |
| 184 | |
| 185 | In such a case, `git merge-base origin/master topic` would return the |
| 186 | parent of B0 in the above picture, but B0^..D is *not* the range of |
| 187 | commits you would want to replay on top of B (it includes B0, which |
| 188 | is not what you wrote; it is a commit the other side discarded when |
| 189 | it moved its tip from B0 to B1). |
| 190 | |
| 191 | `git merge-base --fork-point origin/master topic` is designed to |
| 192 | help in such a case. It takes not only B but also B0, B1, and B2 |
| 193 | (i.e. old tips of the remote-tracking branches your repository's |
| 194 | reflog knows about) into account to see on which commit your topic |
| 195 | branch was built and finds B0, allowing you to replay only the |
| 196 | commits on your topic, excluding the commits the other side later |
| 197 | discarded. |
| 198 | |
| 199 | Hence |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 200 | |
| 201 | $ fork_point=$(git merge-base --fork-point origin/master topic) |
Junio C Hamano | 6d1700b | 2017-11-09 11:49:45 +0900 | [diff] [blame] | 202 | |
| 203 | will find B0, and |
| 204 | |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 205 | $ git rebase --onto origin/master $fork_point topic |
| 206 | |
Elijah Newren | 4d54268 | 2023-10-08 06:45:24 +0000 | [diff] [blame] | 207 | will replay D0, D1, and D on top of B to create a new history of this |
Junio C Hamano | 6d1700b | 2017-11-09 11:49:45 +0900 | [diff] [blame] | 208 | shape: |
| 209 | |
Martin Ågren | 922a2c9 | 2019-09-07 16:12:48 +0200 | [diff] [blame] | 210 | .... |
| 211 | o---B2 |
| 212 | / |
| 213 | ---o---o---B1--o---o---o---B (origin/master) |
| 214 | \ \ |
| 215 | B0 D0'--D1'--D' (topic - updated) |
| 216 | \ |
| 217 | D0---D1---D (topic - old) |
| 218 | .... |
Junio C Hamano | 6d1700b | 2017-11-09 11:49:45 +0900 | [diff] [blame] | 219 | |
| 220 | A caveat is that older reflog entries in your repository may be |
| 221 | expired by `git gc`. If B0 no longer appears in the reflog of the |
| 222 | remote-tracking branch `origin/master`, the `--fork-point` mode |
| 223 | obviously cannot find it and fails, avoiding to give a random and |
| 224 | useless result (such as the parent of B0, like the same command |
| 225 | without the `--fork-point` option gives). |
| 226 | |
| 227 | Also, the remote-tracking branch you use the `--fork-point` mode |
| 228 | with must be the one your topic forked from its tip. If you forked |
| 229 | from an older commit than the tip, this mode would not find the fork |
| 230 | point (imagine in the above sample history B0 did not exist, |
| 231 | origin/master started at B1, moved to B2 and then B, and you forked |
| 232 | your topic at origin/master^ when origin/master was B1; the shape of |
| 233 | the history would be the same as above, without B0, and the parent |
| 234 | of B1 is what `git merge-base origin/master topic` correctly finds, |
| 235 | but the `--fork-point` mode will not, because it is not one of the |
| 236 | commits that used to be at the tip of origin/master). |
| 237 | |
Junio C Hamano | 5907cda | 2012-08-30 14:52:20 -0700 | [diff] [blame] | 238 | |
Jonathan Nieder | 1846e9e | 2010-08-17 01:59:55 -0500 | [diff] [blame] | 239 | See also |
| 240 | -------- |
| 241 | linkgit:git-rev-list[1], |
| 242 | linkgit:git-show-branch[1], |
| 243 | linkgit:git-merge[1] |
| 244 | |
David Greaves | 2cf565c | 2005-05-10 22:32:30 +0100 | [diff] [blame] | 245 | GIT |
| 246 | --- |
Christian Couder | 9e1f0a8 | 2008-06-06 09:07:32 +0200 | [diff] [blame] | 247 | Part of the linkgit:git[1] suite |