merge-base --independent to print reduced parent list in a merge

While show-branch --independent does not support more than MAX_REVS
revs, git internally supports more with a different algorithm.
Expose that functionality as "git merge-base --independent".

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:54 -05:00 committed by Junio C Hamano
parent aa8f98c1bf
commit a1e0ad78b7
3 changed files with 62 additions and 7 deletions

View File

@ -8,7 +8,9 @@ git-merge-base - Find as good common ancestors as possible for a merge
SYNOPSIS
--------
[verse]
'git merge-base' [-a|--all] [--octopus] <commit> <commit>...
'git merge-base' --independent <commit>...
DESCRIPTION
-----------
@ -42,6 +44,13 @@ OPTIONS
in preparation for an n-way merge. This mimics the behavior
of 'git show-branch --merge-base'.
--independent::
Instead of printing merge bases, print a minimal subset of
the supplied commits with the same ancestors. In other words,
among the commits given, list those which cannot be reached
from any other. This mimics the behavior of 'git show-branch
--independent'.
DISCUSSION
----------

View File

@ -24,6 +24,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] [--octopus] <commit> <commit>...",
"git merge-base --independent <commit>...",
NULL
};
@ -41,15 +42,19 @@ 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)
static int handle_octopus(int count, const char **args, int reduce, int show_all)
{
struct commit_list *revs = NULL;
struct commit_list *result;
int i;
for (i = count - 1; i >= 0; i++)
if (reduce)
show_all = 1;
for (i = count - 1; i >= 0; i--)
commit_list_insert(get_commit_reference(args[i]), &revs);
result = get_octopus_merge_bases(revs);
result = reduce ? reduce_heads(revs) : get_octopus_merge_bases(revs);
if (!result)
return 1;
@ -70,20 +75,24 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
int rev_nr = 0;
int show_all = 0;
int octopus = 0;
int reduce = 0;
struct option options[] = {
OPT_BOOLEAN('a', "all", &show_all, "output all common ancestors"),
OPT_BOOLEAN(0, "octopus", &octopus, "find ancestors for a single n-way merge"),
OPT_BOOLEAN(0, "independent", &reduce, "list revs not reachable from others"),
OPT_END()
};
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
if (!octopus && argc < 2)
if (!octopus && !reduce && argc < 2)
usage_with_options(merge_base_usage, options);
if (reduce && (show_all || octopus))
die("--independent cannot be used with other options");
if (octopus)
return show_octopus_merge_bases(argc, argv, show_all);
if (octopus || reduce)
return handle_octopus(argc, argv, reduce, show_all);
rev = xmalloc(argc * sizeof(*rev));
while (argc-- > 0)

View File

@ -3,7 +3,7 @@
# Copyright (c) 2005 Junio C Hamano
#
test_description='Merge base computation.
test_description='Merge base and parent list computation.
'
. ./test-lib.sh
@ -75,6 +75,26 @@ test_expect_success 'merge-base G H' '
test_cmp expected actual.sb
'
test_expect_success 'merge-base/show-branch --independent' '
git name-rev "$H" >expected1 &&
git name-rev "$H" "$G" >expected2 &&
parents=$(git merge-base --independent H) &&
git name-rev $parents >actual1.mb &&
parents=$(git merge-base --independent A H G) &&
git name-rev $parents >actual2.mb &&
parents=$(git show-branch --independent H) &&
git name-rev $parents >actual1.sb &&
parents=$(git show-branch --independent A H G) &&
git name-rev $parents >actual2.sb &&
test_cmp expected1 actual1.mb &&
test_cmp expected2 actual2.mb &&
test_cmp expected1 actual1.sb &&
test_cmp expected2 actual2.sb
'
test_expect_success 'unsynchronized clocks' '
# This test is to demonstrate that relying on timestamps in a distributed
# SCM to provide a _consistent_ partial ordering of commits leads to
@ -125,6 +145,23 @@ test_expect_success 'unsynchronized clocks' '
test_cmp expected actual.all
'
test_expect_success '--independent with unsynchronized clocks' '
IB=$(doit 0 IB) &&
I1=$(doit -10 I1 $IB) &&
I2=$(doit -9 I2 $I1) &&
I3=$(doit -8 I3 $I2) &&
I4=$(doit -7 I4 $I3) &&
I5=$(doit -6 I5 $I4) &&
I6=$(doit -5 I6 $I5) &&
I7=$(doit -4 I7 $I6) &&
I8=$(doit -3 I8 $I7) &&
IH=$(doit -2 IH $I8) &&
echo $IH >expected &&
git merge-base --independent IB IH >actual &&
test_cmp expected actual
'
test_expect_success 'merge-base for octopus-step (setup)' '
# Another set to demonstrate base between one commit and a merge
# in the documentation.