Peter Hagervall | baffc0e | 2007-07-15 01:14:45 +0200 | [diff] [blame] | 1 | #include "builtin.h" |
Linus Torvalds | 6683463 | 2005-04-17 12:18:17 -0700 | [diff] [blame] | 2 | #include "cache.h" |
Brandon Williams | b2141fc | 2017-06-14 11:07:36 -0700 | [diff] [blame] | 3 | #include "config.h" |
Daniel Barkalow | b5039db | 2005-04-18 11:39:48 -0700 | [diff] [blame] | 4 | #include "commit.h" |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 5 | #include "refs.h" |
| 6 | #include "diff.h" |
| 7 | #include "revision.h" |
Pierre Habouzit | e5d1a4d | 2008-10-02 14:59:19 +0200 | [diff] [blame] | 8 | #include "parse-options.h" |
Stefan Beller | 2122f67 | 2018-06-28 18:21:58 -0700 | [diff] [blame] | 9 | #include "repository.h" |
Derrick Stolee | 6404355 | 2018-07-20 16:33:04 +0000 | [diff] [blame] | 10 | #include "commit-reach.h" |
Linus Torvalds | 6683463 | 2005-04-17 12:18:17 -0700 | [diff] [blame] | 11 | |
Christian Couder | 53eda89 | 2008-07-30 07:04:14 +0200 | [diff] [blame] | 12 | static int show_merge_base(struct commit **rev, int rev_nr, int show_all) |
Johannes Schindelin | 52cab8a | 2006-06-29 15:16:46 +0200 | [diff] [blame] | 13 | { |
Martin Ågren | a452d0f | 2017-11-07 21:39:44 +0100 | [diff] [blame] | 14 | struct commit_list *result, *r; |
Christian Couder | 53eda89 | 2008-07-30 07:04:14 +0200 | [diff] [blame] | 15 | |
Junio C Hamano | 2ce406c | 2014-10-30 12:20:44 -0700 | [diff] [blame] | 16 | result = get_merge_bases_many_dirty(rev[0], rev_nr - 1, rev + 1); |
Johannes Schindelin | 52cab8a | 2006-06-29 15:16:46 +0200 | [diff] [blame] | 17 | |
| 18 | if (!result) |
| 19 | return 1; |
| 20 | |
Martin Ågren | a452d0f | 2017-11-07 21:39:44 +0100 | [diff] [blame] | 21 | for (r = result; r; r = r->next) { |
| 22 | printf("%s\n", oid_to_hex(&r->item->object.oid)); |
Junio C Hamano | 9585e40 | 2005-08-23 21:08:59 -0700 | [diff] [blame] | 23 | if (!show_all) |
Martin Ågren | a452d0f | 2017-11-07 21:39:44 +0100 | [diff] [blame] | 24 | break; |
Junio C Hamano | 9585e40 | 2005-08-23 21:08:59 -0700 | [diff] [blame] | 25 | } |
Johannes Schindelin | 52cab8a | 2006-06-29 15:16:46 +0200 | [diff] [blame] | 26 | |
Martin Ågren | a452d0f | 2017-11-07 21:39:44 +0100 | [diff] [blame] | 27 | free_commit_list(result); |
Junio C Hamano | 9585e40 | 2005-08-23 21:08:59 -0700 | [diff] [blame] | 28 | return 0; |
Linus Torvalds | 6683463 | 2005-04-17 12:18:17 -0700 | [diff] [blame] | 29 | } |
| 30 | |
Pierre Habouzit | e5d1a4d | 2008-10-02 14:59:19 +0200 | [diff] [blame] | 31 | static const char * const merge_base_usage[] = { |
Alex Henrie | 9c9b4f2 | 2015-01-13 00:44:47 -0700 | [diff] [blame] | 32 | N_("git merge-base [-a | --all] <commit> <commit>..."), |
| 33 | N_("git merge-base [-a | --all] --octopus <commit>..."), |
Nguyễn Thái Ngọc Duy | f037dbf | 2012-08-20 19:32:22 +0700 | [diff] [blame] | 34 | N_("git merge-base --independent <commit>..."), |
Junio C Hamano | 34f5130 | 2012-09-11 11:35:26 -0700 | [diff] [blame] | 35 | N_("git merge-base --is-ancestor <commit> <commit>"), |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 36 | N_("git merge-base --fork-point <ref> [<commit>]"), |
Pierre Habouzit | e5d1a4d | 2008-10-02 14:59:19 +0200 | [diff] [blame] | 37 | NULL |
| 38 | }; |
Junio C Hamano | 9585e40 | 2005-08-23 21:08:59 -0700 | [diff] [blame] | 39 | |
Christian Couder | df57acc | 2008-07-29 07:42:53 +0200 | [diff] [blame] | 40 | static struct commit *get_commit_reference(const char *arg) |
| 41 | { |
brian m. carlson | d0ae910 | 2017-02-21 23:47:36 +0000 | [diff] [blame] | 42 | struct object_id revkey; |
Christian Couder | df57acc | 2008-07-29 07:42:53 +0200 | [diff] [blame] | 43 | struct commit *r; |
| 44 | |
brian m. carlson | d0ae910 | 2017-02-21 23:47:36 +0000 | [diff] [blame] | 45 | if (get_oid(arg, &revkey)) |
Christian Couder | df57acc | 2008-07-29 07:42:53 +0200 | [diff] [blame] | 46 | die("Not a valid object name %s", arg); |
Stefan Beller | 2122f67 | 2018-06-28 18:21:58 -0700 | [diff] [blame] | 47 | r = lookup_commit_reference(the_repository, &revkey); |
Christian Couder | df57acc | 2008-07-29 07:42:53 +0200 | [diff] [blame] | 48 | if (!r) |
| 49 | die("Not a valid commit name %s", arg); |
| 50 | |
| 51 | return r; |
| 52 | } |
| 53 | |
Junio C Hamano | e2f5df4 | 2013-12-30 11:37:49 -0800 | [diff] [blame] | 54 | static int handle_independent(int count, const char **args) |
Jonathan Nieder | aa8f98c | 2010-08-17 02:01:15 -0500 | [diff] [blame] | 55 | { |
Martin Ågren | a452d0f | 2017-11-07 21:39:44 +0100 | [diff] [blame] | 56 | struct commit_list *revs = NULL, *rev; |
Jonathan Nieder | aa8f98c | 2010-08-17 02:01:15 -0500 | [diff] [blame] | 57 | int i; |
| 58 | |
Junio C Hamano | e2f5df4 | 2013-12-30 11:37:49 -0800 | [diff] [blame] | 59 | for (i = count - 1; i >= 0; i--) |
| 60 | commit_list_insert(get_commit_reference(args[i]), &revs); |
| 61 | |
Martin Ågren | 4da7264 | 2017-11-07 21:39:45 +0100 | [diff] [blame] | 62 | reduce_heads_replace(&revs); |
Martin Ågren | a452d0f | 2017-11-07 21:39:44 +0100 | [diff] [blame] | 63 | |
| 64 | if (!revs) |
Junio C Hamano | e2f5df4 | 2013-12-30 11:37:49 -0800 | [diff] [blame] | 65 | return 1; |
| 66 | |
Martin Ågren | a452d0f | 2017-11-07 21:39:44 +0100 | [diff] [blame] | 67 | for (rev = revs; rev; rev = rev->next) |
| 68 | printf("%s\n", oid_to_hex(&rev->item->object.oid)); |
| 69 | |
| 70 | free_commit_list(revs); |
Junio C Hamano | e2f5df4 | 2013-12-30 11:37:49 -0800 | [diff] [blame] | 71 | return 0; |
| 72 | } |
| 73 | |
| 74 | static int handle_octopus(int count, const char **args, int show_all) |
| 75 | { |
| 76 | struct commit_list *revs = NULL; |
Martin Ågren | a452d0f | 2017-11-07 21:39:44 +0100 | [diff] [blame] | 77 | struct commit_list *result, *rev; |
Junio C Hamano | e2f5df4 | 2013-12-30 11:37:49 -0800 | [diff] [blame] | 78 | int i; |
Jonathan Nieder | a1e0ad7 | 2010-08-17 02:01:54 -0500 | [diff] [blame] | 79 | |
| 80 | for (i = count - 1; i >= 0; i--) |
Jonathan Nieder | aa8f98c | 2010-08-17 02:01:15 -0500 | [diff] [blame] | 81 | commit_list_insert(get_commit_reference(args[i]), &revs); |
Jonathan Nieder | a1e0ad7 | 2010-08-17 02:01:54 -0500 | [diff] [blame] | 82 | |
Martin Ågren | 4da7264 | 2017-11-07 21:39:45 +0100 | [diff] [blame] | 83 | result = get_octopus_merge_bases(revs); |
| 84 | free_commit_list(revs); |
| 85 | reduce_heads_replace(&result); |
Jonathan Nieder | aa8f98c | 2010-08-17 02:01:15 -0500 | [diff] [blame] | 86 | |
| 87 | if (!result) |
| 88 | return 1; |
| 89 | |
Martin Ågren | a452d0f | 2017-11-07 21:39:44 +0100 | [diff] [blame] | 90 | for (rev = result; rev; rev = rev->next) { |
| 91 | printf("%s\n", oid_to_hex(&rev->item->object.oid)); |
Jonathan Nieder | aa8f98c | 2010-08-17 02:01:15 -0500 | [diff] [blame] | 92 | if (!show_all) |
Martin Ågren | a452d0f | 2017-11-07 21:39:44 +0100 | [diff] [blame] | 93 | break; |
Jonathan Nieder | aa8f98c | 2010-08-17 02:01:15 -0500 | [diff] [blame] | 94 | } |
| 95 | |
Martin Ågren | a452d0f | 2017-11-07 21:39:44 +0100 | [diff] [blame] | 96 | free_commit_list(result); |
Jonathan Nieder | aa8f98c | 2010-08-17 02:01:15 -0500 | [diff] [blame] | 97 | return 0; |
| 98 | } |
| 99 | |
Junio C Hamano | 5907cda | 2012-08-30 14:52:20 -0700 | [diff] [blame] | 100 | static int handle_is_ancestor(int argc, const char **argv) |
| 101 | { |
| 102 | struct commit *one, *two; |
| 103 | |
| 104 | if (argc != 2) |
| 105 | die("--is-ancestor takes exactly two commits"); |
| 106 | one = get_commit_reference(argv[0]); |
| 107 | two = get_commit_reference(argv[1]); |
| 108 | if (in_merge_bases(one, two)) |
| 109 | return 0; |
| 110 | else |
| 111 | return 1; |
| 112 | } |
| 113 | |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 114 | static int handle_fork_point(int argc, const char **argv) |
| 115 | { |
brian m. carlson | d0ae910 | 2017-02-21 23:47:36 +0000 | [diff] [blame] | 116 | struct object_id oid; |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 117 | char *refname; |
Pratik Karki | 103148a | 2018-09-04 15:00:08 -0700 | [diff] [blame] | 118 | struct commit *derived, *fork_point; |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 119 | const char *commitname; |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 120 | |
brian m. carlson | cca5fa6 | 2017-10-15 22:06:57 +0000 | [diff] [blame] | 121 | switch (dwim_ref(argv[0], strlen(argv[0]), &oid, &refname)) { |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 122 | case 0: |
| 123 | die("No such ref: '%s'", argv[0]); |
| 124 | case 1: |
| 125 | break; /* good */ |
| 126 | default: |
| 127 | die("Ambiguous refname: '%s'", argv[0]); |
| 128 | } |
| 129 | |
| 130 | commitname = (argc == 2) ? argv[1] : "HEAD"; |
brian m. carlson | d0ae910 | 2017-02-21 23:47:36 +0000 | [diff] [blame] | 131 | if (get_oid(commitname, &oid)) |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 132 | die("Not a valid object name: '%s'", commitname); |
| 133 | |
Stefan Beller | 2122f67 | 2018-06-28 18:21:58 -0700 | [diff] [blame] | 134 | derived = lookup_commit_reference(the_repository, &oid); |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 135 | |
Pratik Karki | 103148a | 2018-09-04 15:00:08 -0700 | [diff] [blame] | 136 | fork_point = get_fork_point(refname, derived); |
Jeff King | 4f21454 | 2016-10-12 16:10:40 -0400 | [diff] [blame] | 137 | |
Pratik Karki | 103148a | 2018-09-04 15:00:08 -0700 | [diff] [blame] | 138 | if (!fork_point) |
| 139 | return 1; |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 140 | |
Pratik Karki | 103148a | 2018-09-04 15:00:08 -0700 | [diff] [blame] | 141 | printf("%s\n", oid_to_hex(&fork_point->object.oid)); |
| 142 | return 0; |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 143 | } |
| 144 | |
Junio C Hamano | 71dfbf2 | 2007-01-09 00:50:02 -0800 | [diff] [blame] | 145 | int cmd_merge_base(int argc, const char **argv, const char *prefix) |
Linus Torvalds | 6683463 | 2005-04-17 12:18:17 -0700 | [diff] [blame] | 146 | { |
Christian Couder | 53eda89 | 2008-07-30 07:04:14 +0200 | [diff] [blame] | 147 | struct commit **rev; |
| 148 | int rev_nr = 0; |
Junio C Hamano | 71dfbf2 | 2007-01-09 00:50:02 -0800 | [diff] [blame] | 149 | int show_all = 0; |
Junio C Hamano | 16e57ae | 2013-10-23 16:10:25 -0700 | [diff] [blame] | 150 | int cmdmode = 0; |
Linus Torvalds | 6683463 | 2005-04-17 12:18:17 -0700 | [diff] [blame] | 151 | |
Pierre Habouzit | e5d1a4d | 2008-10-02 14:59:19 +0200 | [diff] [blame] | 152 | struct option options[] = { |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 153 | OPT_BOOL('a', "all", &show_all, N_("output all common ancestors")), |
Junio C Hamano | 16e57ae | 2013-10-23 16:10:25 -0700 | [diff] [blame] | 154 | OPT_CMDMODE(0, "octopus", &cmdmode, |
| 155 | N_("find ancestors for a single n-way merge"), 'o'), |
| 156 | OPT_CMDMODE(0, "independent", &cmdmode, |
| 157 | N_("list revs not reachable from others"), 'r'), |
| 158 | OPT_CMDMODE(0, "is-ancestor", &cmdmode, |
| 159 | N_("is the first one ancestor of the other?"), 'a'), |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 160 | OPT_CMDMODE(0, "fork-point", &cmdmode, |
| 161 | N_("find where <commit> forked from reflog of <ref>"), 'f'), |
Pierre Habouzit | e5d1a4d | 2008-10-02 14:59:19 +0200 | [diff] [blame] | 162 | OPT_END() |
| 163 | }; |
| 164 | |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 165 | git_config(git_default_config, NULL); |
Stephen Boyd | 3778292 | 2009-05-23 11:53:12 -0700 | [diff] [blame] | 166 | argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0); |
Jonathan Nieder | aa8f98c | 2010-08-17 02:01:15 -0500 | [diff] [blame] | 167 | |
Junio C Hamano | 16e57ae | 2013-10-23 16:10:25 -0700 | [diff] [blame] | 168 | if (cmdmode == 'a') { |
| 169 | if (argc < 2) |
| 170 | usage_with_options(merge_base_usage, options); |
| 171 | if (show_all) |
| 172 | die("--is-ancestor cannot be used with --all"); |
| 173 | return handle_is_ancestor(argc, argv); |
| 174 | } |
| 175 | |
| 176 | if (cmdmode == 'r' && show_all) |
| 177 | die("--independent cannot be used with --all"); |
| 178 | |
Junio C Hamano | d5d1678 | 2014-01-10 10:33:32 -0800 | [diff] [blame] | 179 | if (cmdmode == 'o') |
Junio C Hamano | e2f5df4 | 2013-12-30 11:37:49 -0800 | [diff] [blame] | 180 | return handle_octopus(argc, argv, show_all); |
Junio C Hamano | d5d1678 | 2014-01-10 10:33:32 -0800 | [diff] [blame] | 181 | |
| 182 | if (cmdmode == 'r') |
Junio C Hamano | e2f5df4 | 2013-12-30 11:37:49 -0800 | [diff] [blame] | 183 | return handle_independent(argc, argv); |
Junio C Hamano | 16e57ae | 2013-10-23 16:10:25 -0700 | [diff] [blame] | 184 | |
Junio C Hamano | d96855f | 2013-10-23 16:47:32 -0700 | [diff] [blame] | 185 | if (cmdmode == 'f') { |
| 186 | if (argc < 1 || 2 < argc) |
| 187 | usage_with_options(merge_base_usage, options); |
| 188 | return handle_fork_point(argc, argv); |
| 189 | } |
| 190 | |
Junio C Hamano | 16e57ae | 2013-10-23 16:10:25 -0700 | [diff] [blame] | 191 | if (argc < 2) |
| 192 | usage_with_options(merge_base_usage, options); |
Jonathan Nieder | aa8f98c | 2010-08-17 02:01:15 -0500 | [diff] [blame] | 193 | |
Jeff King | b32fa95 | 2016-02-22 17:44:25 -0500 | [diff] [blame] | 194 | ALLOC_ARRAY(rev, argc); |
Pierre Habouzit | e5d1a4d | 2008-10-02 14:59:19 +0200 | [diff] [blame] | 195 | while (argc-- > 0) |
| 196 | rev[rev_nr++] = get_commit_reference(*argv++); |
Christian Couder | 53eda89 | 2008-07-30 07:04:14 +0200 | [diff] [blame] | 197 | return show_merge_base(rev, rev_nr, show_all); |
Linus Torvalds | 6683463 | 2005-04-17 12:18:17 -0700 | [diff] [blame] | 198 | } |