summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2013-03-28 14:37:53 -0700
committerLibravatar Junio C Hamano <gitster@pobox.com>2013-03-28 14:37:53 -0700
commit436b60ce7aac4cf8e496c57c9baae46094571b22 (patch)
tree7caa04a8f179fa651146ea2ab03fd5724ba5088d
parentMerge branch 'jk/checkout-attribute-lookup' (diff)
parentsimplify-merges: drop merge from irrelevant side branch (diff)
downloadtgif-436b60ce7aac4cf8e496c57c9baae46094571b22.tar.xz
Merge branch 'jc/remove-treesame-parent-in-simplify-merges'
The --simplify-merges logic did not cull irrelevant parents from a merge that is otherwise not interesting with respect to the paths we are following. This touches a fairly core part of the revision traversal infrastructure; even though I think this change is correct, please report immediately if you find any unintended side effect. * jc/remove-treesame-parent-in-simplify-merges: simplify-merges: drop merge from irrelevant side branch
-rw-r--r--revision.c30
-rwxr-xr-xt/t6012-rev-list-simplify.sh26
2 files changed, 48 insertions, 8 deletions
diff --git a/revision.c b/revision.c
index ef60205412..78397d6486 100644
--- a/revision.c
+++ b/revision.c
@@ -1970,6 +1970,22 @@ static struct merge_simplify_state *locate_simplify_state(struct rev_info *revs,
return st;
}
+static void remove_treesame_parents(struct commit *commit)
+{
+ struct commit_list **pp, *p;
+
+ pp = &commit->parents;
+ while ((p = *pp) != NULL) {
+ struct commit *parent = p->item;
+ if (parent->object.flags & TREESAME) {
+ *pp = p->next;
+ free(p);
+ continue;
+ }
+ pp = &p->next;
+ }
+}
+
static struct commit_list **simplify_one(struct rev_info *revs, struct commit *commit, struct commit_list **tail)
{
struct commit_list *p;
@@ -2022,10 +2038,18 @@ static struct commit_list **simplify_one(struct rev_info *revs, struct commit *c
if (revs->first_parent_only)
break;
}
- if (!revs->first_parent_only)
- cnt = remove_duplicate_parents(commit);
- else
+
+ if (revs->first_parent_only) {
cnt = 1;
+ } else {
+ /*
+ * A merge with a tree-same parent is useless
+ */
+ if (commit->parents && commit->parents->next)
+ remove_treesame_parents(commit);
+
+ cnt = remove_duplicate_parents(commit);
+ }
/*
* It is possible that we are a merge and one side branch
diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh
index 839ad97b79..8e2ff13423 100755
--- a/t/t6012-rev-list-simplify.sh
+++ b/t/t6012-rev-list-simplify.sh
@@ -56,7 +56,23 @@ test_expect_success setup '
echo "Final change" >file &&
test_tick && git commit -a -m "Final change" &&
- note I
+ note I &&
+
+ git symbolic-ref HEAD refs/heads/unrelated &&
+ git rm -f "*" &&
+ echo "Unrelated branch" >side &&
+ git add side &&
+ test_tick && git commit -m "Side root" &&
+ note J &&
+
+ git checkout master &&
+ test_tick && git merge -m "Coolest" unrelated &&
+ note K &&
+
+ echo "Immaterial" >elif &&
+ git add elif &&
+ test_tick && git commit -m "Last" &&
+ note L
'
FMT='tformat:%P %H | %s'
@@ -79,10 +95,10 @@ check_result () {
'
}
-check_result 'I H G F E D C B A' --full-history
-check_result 'I H E C B A' --full-history -- file
-check_result 'I H E C B A' --full-history --topo-order -- file
-check_result 'I H E C B A' --full-history --date-order -- file
+check_result 'L K J I H G F E D C B A' --full-history
+check_result 'K I H E C B A' --full-history -- file
+check_result 'K I H E C B A' --full-history --topo-order -- file
+check_result 'K I H E C B A' --full-history --date-order -- file
check_result 'I E C B A' --simplify-merges -- file
check_result 'I B A' -- file
check_result 'I B A' --topo-order -- file