Skip to content

Commit

Permalink
simplify-merges: drop merge from irrelevant side branch
Browse files Browse the repository at this point in the history
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 <gitster@pobox.com>
  • Loading branch information
Junio C Hamano committed Jan 17, 2013
1 parent faf0156 commit 4b7f53d
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 5 deletions.
23 changes: 23 additions & 0 deletions revision.c
Original file line number Diff line number Diff line change
Expand Up @@ -1424,6 +1424,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;
Expand Down Expand Up @@ -1469,6 +1485,13 @@ static struct commit_list **simplify_one(struct rev_info *revs, struct commit *c
pst = locate_simplify_state(revs, p->item);
p->item = pst->simplified;
}

/*
* A merge with a tree-same parent is useless
*/
if (commit->parents && commit->parents->next)
remove_treesame_parents(commit);

cnt = remove_duplicate_parents(commit);

/*
Expand Down
26 changes: 21 additions & 5 deletions t/t6012-rev-list-simplify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,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'
Expand All @@ -82,10 +98,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
Expand Down

0 comments on commit 4b7f53d

Please sign in to comment.