blob: 4f30f1b0c8b14e78e272ec54a86584d66501f754 [file] [log] [blame]
Peter Hagervallbaffc0e2007-07-15 01:14:45 +02001#include "builtin.h"
Linus Torvalds66834632005-04-17 12:18:17 -07002#include "cache.h"
Daniel Barkalowb5039db2005-04-18 11:39:48 -07003#include "commit.h"
Pierre Habouzite5d1a4d2008-10-02 14:59:19 +02004#include "parse-options.h"
Linus Torvalds66834632005-04-17 12:18:17 -07005
Christian Couder53eda892008-07-30 07:04:14 +02006static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
Johannes Schindelin52cab8a2006-06-29 15:16:46 +02007{
Christian Couder53eda892008-07-30 07:04:14 +02008 struct commit_list *result;
9
10 result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1, 0);
Johannes Schindelin52cab8a2006-06-29 15:16:46 +020011
12 if (!result)
13 return 1;
14
Junio C Hamano9585e402005-08-23 21:08:59 -070015 while (result) {
Johannes Schindelin52cab8a2006-06-29 15:16:46 +020016 printf("%s\n", sha1_to_hex(result->item->object.sha1));
Junio C Hamano9585e402005-08-23 21:08:59 -070017 if (!show_all)
18 return 0;
Johannes Schindelin52cab8a2006-06-29 15:16:46 +020019 result = result->next;
Junio C Hamano9585e402005-08-23 21:08:59 -070020 }
Johannes Schindelin52cab8a2006-06-29 15:16:46 +020021
Junio C Hamano9585e402005-08-23 21:08:59 -070022 return 0;
Linus Torvalds66834632005-04-17 12:18:17 -070023}
24
Pierre Habouzite5d1a4d2008-10-02 14:59:19 +020025static const char * const merge_base_usage[] = {
Vincent van Ravesteijn57294822011-04-15 10:34:03 +020026 "git merge-base [-a|--all] <commit> <commit>...",
27 "git merge-base [-a|--all] --octopus <commit>...",
Jonathan Niedera1e0ad72010-08-17 02:01:54 -050028 "git merge-base --independent <commit>...",
Pierre Habouzite5d1a4d2008-10-02 14:59:19 +020029 NULL
30};
Junio C Hamano9585e402005-08-23 21:08:59 -070031
Christian Couderdf57acc2008-07-29 07:42:53 +020032static struct commit *get_commit_reference(const char *arg)
33{
34 unsigned char revkey[20];
35 struct commit *r;
36
37 if (get_sha1(arg, revkey))
38 die("Not a valid object name %s", arg);
39 r = lookup_commit_reference(revkey);
40 if (!r)
41 die("Not a valid commit name %s", arg);
42
43 return r;
44}
45
Jonathan Niedera1e0ad72010-08-17 02:01:54 -050046static int handle_octopus(int count, const char **args, int reduce, int show_all)
Jonathan Niederaa8f98c2010-08-17 02:01:15 -050047{
48 struct commit_list *revs = NULL;
49 struct commit_list *result;
50 int i;
51
Jonathan Niedera1e0ad72010-08-17 02:01:54 -050052 if (reduce)
53 show_all = 1;
54
55 for (i = count - 1; i >= 0; i--)
Jonathan Niederaa8f98c2010-08-17 02:01:15 -050056 commit_list_insert(get_commit_reference(args[i]), &revs);
Jonathan Niedera1e0ad72010-08-17 02:01:54 -050057
58 result = reduce ? reduce_heads(revs) : get_octopus_merge_bases(revs);
Jonathan Niederaa8f98c2010-08-17 02:01:15 -050059
60 if (!result)
61 return 1;
62
63 while (result) {
64 printf("%s\n", sha1_to_hex(result->item->object.sha1));
65 if (!show_all)
66 return 0;
67 result = result->next;
68 }
69
70 return 0;
71}
72
Junio C Hamano71dfbf22007-01-09 00:50:02 -080073int cmd_merge_base(int argc, const char **argv, const char *prefix)
Linus Torvalds66834632005-04-17 12:18:17 -070074{
Christian Couder53eda892008-07-30 07:04:14 +020075 struct commit **rev;
76 int rev_nr = 0;
Junio C Hamano71dfbf22007-01-09 00:50:02 -080077 int show_all = 0;
Jonathan Niederaa8f98c2010-08-17 02:01:15 -050078 int octopus = 0;
Jonathan Niedera1e0ad72010-08-17 02:01:54 -050079 int reduce = 0;
Linus Torvalds66834632005-04-17 12:18:17 -070080
Pierre Habouzite5d1a4d2008-10-02 14:59:19 +020081 struct option options[] = {
Jonathan Niederaa8f98c2010-08-17 02:01:15 -050082 OPT_BOOLEAN('a', "all", &show_all, "output all common ancestors"),
83 OPT_BOOLEAN(0, "octopus", &octopus, "find ancestors for a single n-way merge"),
Jonathan Niedera1e0ad72010-08-17 02:01:54 -050084 OPT_BOOLEAN(0, "independent", &reduce, "list revs not reachable from others"),
Pierre Habouzite5d1a4d2008-10-02 14:59:19 +020085 OPT_END()
86 };
87
Johannes Schindelinef90d6d2008-05-14 18:46:53 +010088 git_config(git_default_config, NULL);
Stephen Boyd37782922009-05-23 11:53:12 -070089 argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
Jonathan Niedera1e0ad72010-08-17 02:01:54 -050090 if (!octopus && !reduce && argc < 2)
Pierre Habouzite5d1a4d2008-10-02 14:59:19 +020091 usage_with_options(merge_base_usage, options);
Jonathan Niedera1e0ad72010-08-17 02:01:54 -050092 if (reduce && (show_all || octopus))
93 die("--independent cannot be used with other options");
Jonathan Niederaa8f98c2010-08-17 02:01:15 -050094
Jonathan Niedera1e0ad72010-08-17 02:01:54 -050095 if (octopus || reduce)
96 return handle_octopus(argc, argv, reduce, show_all);
Jonathan Niederaa8f98c2010-08-17 02:01:15 -050097
Pierre Habouzite5d1a4d2008-10-02 14:59:19 +020098 rev = xmalloc(argc * sizeof(*rev));
99 while (argc-- > 0)
100 rev[rev_nr++] = get_commit_reference(*argv++);
Christian Couder53eda892008-07-30 07:04:14 +0200101 return show_merge_base(rev, rev_nr, show_all);
Linus Torvalds66834632005-04-17 12:18:17 -0700102}