merge-base --octopus to mimic show-branch --merge-base

While show-branch --merge-base does not support more than MAX_REVS
revs, git supports more with a different algorithm
(v1.6.0-rc0~51^2~13, Introduce get_octopus_merge_bases() in commit.c,
2008-06-27).  Expose that functionality.

This should help scripts to catch up with builtin merge in supporting
dodecapus.

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jonathan Nieder 2010-08-17 02:01:15 -05:00 committed by Junio C Hamano
parent 1846e9edf6
commit aa8f98c1bf
3 changed files with 46 additions and 10 deletions

View file

@ -8,7 +8,7 @@ git-merge-base - Find as good common ancestors as possible for a merge
SYNOPSIS
--------
'git merge-base' [-a|--all] <commit> <commit>...
'git merge-base' [-a|--all] [--octopus] <commit> <commit>...
DESCRIPTION
-----------
@ -20,12 +20,12 @@ that does not have any better common ancestor is a 'best common
ancestor', i.e. a 'merge base'. Note that there can be more than one
merge base for a pair of commits.
Among the two commits to compute the merge base from, one is specified by
the first commit argument on the command line; the other commit is a
(possibly hypothetical) commit that is a merge across all the remaining
commits on the command line. As the most common special case, specifying only
two commits on the command line means computing the merge base between
the given two commits.
Unless `--octopus` is given, among the two commits to compute the merge
base from, one is specified by the first commit argument on the command
line; the other commit is a (possibly hypothetical) commit that is a merge
across all the remaining commits on the command line. As the most common
special case, specifying only two commits on the command line means
computing the merge base between the given two commits.
As a consequence, the 'merge base' is not necessarily contained in each of the
commit arguments if more than two commits are specified. This is different
@ -37,6 +37,11 @@ OPTIONS
--all::
Output all merge bases for the commits, instead of just one.
--octopus::
Compute the best common ancestors of all supplied commits,
in preparation for an n-way merge. This mimics the behavior
of 'git show-branch --merge-base'.
DISCUSSION
----------

View file

@ -23,7 +23,7 @@ static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
}
static const char * const merge_base_usage[] = {
"git merge-base [-a|--all] <commit> <commit>...",
"git merge-base [-a|--all] [--octopus] <commit> <commit>...",
NULL
};
@ -41,21 +41,50 @@ static struct commit *get_commit_reference(const char *arg)
return r;
}
static int show_octopus_merge_bases(int count, const char **args, int show_all)
{
struct commit_list *revs = NULL;
struct commit_list *result;
int i;
for (i = count - 1; i >= 0; i++)
commit_list_insert(get_commit_reference(args[i]), &revs);
result = get_octopus_merge_bases(revs);
if (!result)
return 1;
while (result) {
printf("%s\n", sha1_to_hex(result->item->object.sha1));
if (!show_all)
return 0;
result = result->next;
}
return 0;
}
int cmd_merge_base(int argc, const char **argv, const char *prefix)
{
struct commit **rev;
int rev_nr = 0;
int show_all = 0;
int octopus = 0;
struct option options[] = {
OPT_BOOLEAN('a', "all", &show_all, "outputs all common ancestors"),
OPT_BOOLEAN('a', "all", &show_all, "output all common ancestors"),
OPT_BOOLEAN(0, "octopus", &octopus, "find ancestors for a single n-way merge"),
OPT_END()
};
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
if (argc < 2)
if (!octopus && argc < 2)
usage_with_options(merge_base_usage, options);
if (octopus)
return show_octopus_merge_bases(argc, argv, show_all);
rev = xmalloc(argc * sizeof(*rev));
while (argc-- > 0)
rev[rev_nr++] = get_commit_reference(*argv++);

View file

@ -164,9 +164,11 @@ test_expect_success 'merge-base A B C' '
git rev-parse --verify MMR >expected.sb &&
git merge-base --all MMA MMB MMC >actual &&
git merge-base --all --octopus MMA MMB MMC >actual.common &&
git show-branch --merge-base MMA MMB MMC >actual.sb &&
test_cmp expected actual &&
test_cmp expected.sb actual.common &&
test_cmp expected.sb actual.sb
'