Skip to content

Commit 4b7f53d

Browse files
committed
simplify-merges: drop merge from irrelevant side branch
The merge simplification rule stated in 6546b59 (revision traversal: show full history with merge simplification, 2008-07-31) still treated merge commits too specially. Namely, in a history with this shape: ---o---o---M / x---x---x where three 'x' were on a history completely unrelated to the main history 'o' and do not touch any of the paths we are following, we still said that after simplifying all of the parents of M, 'x' (which is the leftmost 'x' that rightmost 'x simplifies down to) and 'o' (which would be the last commit on the main history that touches the paths we are following) are independent from each other, and both need to be kept. That is incorrect; when the side branch 'x' never touches the paths, it should be removed to allow M to simplify down to the last commit on the main history that touches the paths. Signed-off-by: Junio C Hamano <[email protected]>
1 parent faf0156 commit 4b7f53d

File tree

2 files changed

+44
-5
lines changed

2 files changed

+44
-5
lines changed

revision.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,22 @@ static struct merge_simplify_state *locate_simplify_state(struct rev_info *revs,
14241424
return st;
14251425
}
14261426

1427+
static void remove_treesame_parents(struct commit *commit)
1428+
{
1429+
struct commit_list **pp, *p;
1430+
1431+
pp = &commit->parents;
1432+
while ((p = *pp) != NULL) {
1433+
struct commit *parent = p->item;
1434+
if (parent->object.flags & TREESAME) {
1435+
*pp = p->next;
1436+
free(p);
1437+
continue;
1438+
}
1439+
pp = &p->next;
1440+
}
1441+
}
1442+
14271443
static struct commit_list **simplify_one(struct rev_info *revs, struct commit *commit, struct commit_list **tail)
14281444
{
14291445
struct commit_list *p;
@@ -1469,6 +1485,13 @@ static struct commit_list **simplify_one(struct rev_info *revs, struct commit *c
14691485
pst = locate_simplify_state(revs, p->item);
14701486
p->item = pst->simplified;
14711487
}
1488+
1489+
/*
1490+
* A merge with a tree-same parent is useless
1491+
*/
1492+
if (commit->parents && commit->parents->next)
1493+
remove_treesame_parents(commit);
1494+
14721495
cnt = remove_duplicate_parents(commit);
14731496

14741497
/*

t/t6012-rev-list-simplify.sh

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,23 @@ test_expect_success setup '
5959
6060
echo "Final change" >file &&
6161
test_tick && git commit -a -m "Final change" &&
62-
note I
62+
note I &&
63+
64+
git symbolic-ref HEAD refs/heads/unrelated &&
65+
git rm -f "*" &&
66+
echo "Unrelated branch" >side &&
67+
git add side &&
68+
test_tick && git commit -m "Side root" &&
69+
note J &&
70+
71+
git checkout master &&
72+
test_tick && git merge -m "Coolest" unrelated &&
73+
note K &&
74+
75+
echo "Immaterial" >elif &&
76+
git add elif &&
77+
test_tick && git commit -m "Last" &&
78+
note L
6379
'
6480

6581
FMT='tformat:%P %H | %s'
@@ -82,10 +98,10 @@ check_result () {
8298
'
8399
}
84100

85-
check_result 'I H G F E D C B A' --full-history
86-
check_result 'I H E C B A' --full-history -- file
87-
check_result 'I H E C B A' --full-history --topo-order -- file
88-
check_result 'I H E C B A' --full-history --date-order -- file
101+
check_result 'L K J I H G F E D C B A' --full-history
102+
check_result 'K I H E C B A' --full-history -- file
103+
check_result 'K I H E C B A' --full-history --topo-order -- file
104+
check_result 'K I H E C B A' --full-history --date-order -- file
89105
check_result 'I E C B A' --simplify-merges -- file
90106
check_result 'I B A' -- file
91107
check_result 'I B A' --topo-order -- file

0 commit comments

Comments
 (0)