summaryrefslogtreecommitdiff
path: root/revision.c
diff options
context:
space:
mode:
authorKevin Bracey <kevin@bracey.fi>2013-05-16 18:32:37 +0300
committerJunio C Hamano <gitster@pobox.com>2013-05-16 11:51:09 -0700
commit143f1eafdb0d326b1a8e3d15bf59a497b9440bf1 (patch)
tree4d0bcbc1d3556b68a055cfd76dabfbbd51d33517 /revision.c
parent9c129eab99f16d7bb174b35573e68ae6a5d02efe (diff)
downloadgit-143f1eafdb0d326b1a8e3d15bf59a497b9440bf1.tar.gz
simplify-merges: drop merge from irrelevant side branch
Reimplement commit 4b7f53da on top of the new simplify-merges infrastructure, tightening the condition to only consider root parents; the original version incorrectly dropped parents that were TREESAME to anything. Original log message follows. 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. Suggested-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Kevin Bracey <kevin@bracey.fi> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'revision.c')
-rw-r--r--revision.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/revision.c b/revision.c
index 62f399c22f..4f7446c359 100644
--- a/revision.c
+++ b/revision.c
@@ -2136,6 +2136,22 @@ static int mark_redundant_parents(struct rev_info *revs, struct commit *commit)
return marked;
}
+static int mark_treesame_root_parents(struct rev_info *revs, struct commit *commit)
+{
+ struct commit_list *p;
+ int marked = 0;
+
+ for (p = commit->parents; p; p = p->next) {
+ struct commit *parent = p->item;
+ if (!parent->parents && (parent->object.flags & TREESAME)) {
+ parent->object.flags |= TMP_MARK;
+ marked++;
+ }
+ }
+
+ return marked;
+}
+
/*
* Awkward naming - this means one parent we are TREESAME to.
* cf mark_treesame_root_parents: root parents that are TREESAME (to an
@@ -2301,10 +2317,18 @@ static struct commit_list **simplify_one(struct rev_info *revs, struct commit *c
* / / o: a commit that touches the paths;
* ---o----'
*
- * Detect and simplify this case.
+ * Further, a merge of an independent branch that doesn't
+ * touch the path will reduce to a treesame root parent:
+ *
+ * ----o----X X: the commit we are looking at;
+ * / o: a commit that touches the paths;
+ * r r: a root commit not touching the paths
+ *
+ * Detect and simplify both cases.
*/
if (1 < cnt) {
int marked = mark_redundant_parents(revs, commit);
+ marked += mark_treesame_root_parents(revs, commit);
if (marked)
marked -= leave_one_treesame_to_parent(revs, commit);
if (marked)