summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 2a29da7)
raw | patch | inline | side by side (parent: 2a29da7)
author | Junio C Hamano <junkio@cox.net> | |
Wed, 24 Aug 2005 04:08:59 +0000 (21:08 -0700) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Wed, 24 Aug 2005 04:08:59 +0000 (21:08 -0700) |
The merge-base command acquires a new option, '--all', that causes it
to output all the common ancestor candidates. The "git resolve"
command then uses it to pick the optimum merge base by picking the one
that results in the smallest number of nontrivial merges.
Signed-off-by: Junio C Hamano <junkio@cox.net>
to output all the common ancestor candidates. The "git resolve"
command then uses it to pick the optimum merge base by picking the one
that results in the smallest number of nontrivial merges.
Signed-off-by: Junio C Hamano <junkio@cox.net>
git-resolve-script | patch | blob | history | |
merge-base.c | patch | blob | history |
diff --git a/git-resolve-script b/git-resolve-script
index 50d5f8336feec0eb9839a2641cb9faf9ab67391d..7c0e3d8aa8f7e63d1e98b79612844043a8481011 100755 (executable)
--- a/git-resolve-script
+++ b/git-resolve-script
dropheads
exit 0
fi
-echo "Trying to merge $merge into $head"
+
+# Find an optimum merge base if there are more than one candidates.
+LF='
+'
+common=$(git-merge-base -a $head $merge)
+case "$common" in
+?*"$LF"?*)
+ echo "Trying to find the optimum merge base."
+ G=.tmp-index$$
+ best=
+ best_cnt=-1
+ for c in $common
+ do
+ rm -f $G
+ GIT_INDEX_FILE=$G git-read-tree -m $c $head $merge \
+ 2>/dev/null || continue
+ # Count the paths that are unmerged.
+ cnt=`GIT_INDEX_FILE=$G git-ls-files --unmerged | wc -l`
+ if test $best_cnt -le 0 -o $cnt -le $best_cnt
+ then
+ best=$c
+ best_cnt=$cnt
+ if test "$best_cnt" -eq 0
+ then
+ # Cannot do any better than all trivial merge.
+ break
+ fi
+ fi
+ done
+ rm -f $G
+ common="$best"
+esac
+
+echo "Trying to merge $merge into $head using $common."
+git-update-cache --refresh 2>/dev/null
git-read-tree -u -m $common $head $merge || exit 1
result_tree=$(git-write-tree 2> /dev/null)
if [ $? -ne 0 ]; then
diff --git a/merge-base.c b/merge-base.c
index 923256c821582f38daffed4fb0df2a97fe66d74b..286bf0e8d1522ac4cf01f75343da40ddff6bf6e8 100644 (file)
--- a/merge-base.c
+++ b/merge-base.c
* commit B.
*/
-static struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
+static int show_all = 0;
+
+static int merge_base(struct commit *rev1, struct commit *rev2)
{
struct commit_list *list = NULL;
struct commit_list *result = NULL;
- if (rev1 == rev2)
- return rev1;
+ if (rev1 == rev2) {
+ printf("%s\n", sha1_to_hex(rev1->object.sha1));
+ return 0;
+ }
parse_commit(rev1);
parse_commit(rev2);
if (flags == 3) {
insert_by_date(commit, &result);
- /* Mark children of a found merge uninteresting */
+ /* Mark parents of a found merge uninteresting */
flags |= UNINTERESTING;
}
parents = commit->parents;
@@ -122,26 +126,46 @@ static struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
insert_by_date(p, &list);
}
}
- return interesting(result);
+
+ if (!result)
+ return 1;
+
+ while (result) {
+ struct commit *commit = result->item;
+ result = result->next;
+ if (commit->object.flags & UNINTERESTING)
+ continue;
+ printf("%s\n", sha1_to_hex(commit->object.sha1));
+ if (!show_all)
+ return 0;
+ commit->object.flags |= UNINTERESTING;
+ }
+ return 0;
}
+static const char merge_base_usage[] =
+"git-merge-base [--all] <commit-id> <commit-id>";
+
int main(int argc, char **argv)
{
- struct commit *rev1, *rev2, *ret;
+ struct commit *rev1, *rev2;
unsigned char rev1key[20], rev2key[20];
+ while (1 < argc && argv[1][0] == '-') {
+ char *arg = argv[1];
+ if (!strcmp(arg, "-a") || !strcmp(arg, "--all"))
+ show_all = 1;
+ else
+ usage(merge_base_usage);
+ argc--; argv++;
+ }
if (argc != 3 ||
get_sha1(argv[1], rev1key) ||
- get_sha1(argv[2], rev2key)) {
- usage("git-merge-base <commit-id> <commit-id>");
- }
+ get_sha1(argv[2], rev2key))
+ usage(merge_base_usage);
rev1 = lookup_commit_reference(rev1key);
rev2 = lookup_commit_reference(rev2key);
if (!rev1 || !rev2)
return 1;
- ret = common_ancestor(rev1, rev2);
- if (!ret)
- return 1;
- printf("%s\n", sha1_to_hex(ret->object.sha1));
- return 0;
+ return merge_base(rev1, rev2);
}