git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 2/7] add option to only visit the first parent of a equal tree merge

From
BLBernhard R. Link <brlink@debian.org>
Date
Nov 30, 2009, 14:44 UTC
Message-ID
<590501c88c7a7b4a7c0c29543775060d4b0e2316.1259524136.git.brlink@debian.org>
In-Reply-To
<cover.1259524136.git.brlink@debian.org>

rev_info gets a new flag first_equal_tree_only that causes revision walks to ignore all but the first parent of equal tree merges. The default is off and there are options --first-equal-tree-only and --all-equal-trees to switch it on/off respectively.

TODO:
 - manpage updates
 - check interaction with some of the other options
---
 revision.c |   57 ++++++++++++++++++++++++++++++++++++++++++++++++---------
 revision.h |    1 +
 2 files changed, 49 insertions(+), 9 deletions(-)
diff --git a/revision.c b/revision.c
index a8a3c3a..fb019d6 100644
--- a/revision.c
+++ b/revision.c
@@ -452,6 +452,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
 	struct commit_list *parent = commit->parents;
 	unsigned left_flag;
 	struct commit_list *cached_base = cache_ptr ? *cache_ptr : NULL;
+	int first_parent_only;
 
 	if (commit->object.flags & ADDED)
 		return 0;
@@ -499,6 +500,21 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
 
 	left_flag = (commit->object.flags & SYMMETRIC_LEFT);
 
+	if (revs->first_parent_only)
+		first_parent_only = 1;
+	else if (revs->first_equal_tree_only && commit->parents) {
+		for (parent = commit->parents; parent; parent = parent->next) {
+			struct commit *p = parent->item;
+
+			if (parse_commit(p) < 0)
+				return -1;
+			if (p->tree != commit->tree)
+				break;
+		}
+		first_parent_only = !parent;
+	} else
+		first_parent_only = 0;
+
 	for (parent = commit->parents; parent; parent = parent->next) {
 		struct commit *p = parent->item;
 
@@ -511,7 +527,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
 			p->object.flags |= SEEN;
 			insert_by_date_cached(p, list, cached_base, cache_ptr);
 		}
-		if (revs->first_parent_only)
+		if (first_parent_only)
 			break;
 	}
 	return 0;
@@ -1067,6 +1083,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		revs->min_age = approxidate(arg + 8);
 	} else if (!strcmp(arg, "--first-parent")) {
 		revs->first_parent_only = 1;
+	} else if (!strcmp(arg, "--first-equal-tree-only")) {
+		revs->first_equal_tree_only = 1;
+	} else if (!strcmp(arg, "--all-equal-trees")) {
+		revs->first_equal_tree_only = 0;
 	} else if (!strcmp(arg, "-g") || !strcmp(arg, "--walk-reflogs")) {
 		init_reflog_walk(&revs->reflog_info);
 	} else if (!strcmp(arg, "--default")) {
@@ -1912,6 +1932,16 @@ static void create_boundary_commit_list(struct rev_info *revs)
 	sort_in_topological_order(&revs->commits, revs->lifo);
 }
 
+static inline void add_boundary_commit(struct rev_info *revs, struct commit *c) {
+	struct object *p = &c->object;
+
+	if (p->flags & (CHILD_SHOWN | SHOWN))
+		return;
+	p->flags |= CHILD_SHOWN;
+	gc_boundary(&revs->boundary_commits);
+	add_object_array(p, NULL, &revs->boundary_commits);
+}
+
 static struct commit *get_revision_internal(struct rev_info *revs)
 {
 	struct commit *c = NULL;
@@ -1987,16 +2017,25 @@ static struct commit *get_revision_internal(struct rev_info *revs)
 	 * 'c', we need to mark its parents that they could be boundaries.
 	 */
 
-	for (l = c->parents; l; l = l->next) {
-		struct object *p;
-		p = &(l->item->object);
-		if (p->flags & (CHILD_SHOWN | SHOWN))
-			continue;
-		p->flags |= CHILD_SHOWN;
-		gc_boundary(&revs->boundary_commits);
-		add_object_array(p, NULL, &revs->boundary_commits);
+	if (revs->first_equal_tree_only && c->parents) {
+		for (l = c->parents; l; l = l->next) {
+			struct commit *p = l->item;
+			parse_commit(p);
+			if (c->tree != p->tree)
+				break;
+		}
+		/* if all parents have the same tree as this node,
+		 * it's an equal tree merge, so ignore all but the
+		 * first parent */
+		if (!l) {
+			add_boundary_commit(revs, c->parents->item);
+			return c;
+		}
 	}
 
+	for (l = c->parents; l; l = l->next) {
+		add_boundary_commit(revs, l->item);
+	}
 	return c;
 }
 
diff --git a/revision.h b/revision.h
index d368003..7ac263c 100644
--- a/revision.h
+++ b/revision.h
@@ -64,6 +64,7 @@ struct rev_info {
 			reverse_output_stage:1,
 			cherry_pick:1,
 			bisect:1,
+			first_equal_tree_only:1,
 			first_parent_only:1;
 
 	/* Diff flags */
Previous: Michael J GruberNext: Bernhard R. Link
Message 4 of 29 in “equal-tree-merges as way to make rebases fast-forward-able”
  1. Bernhard R. LinkNov 30, 2009
  2. 1/7 add new command git equal-tree-markerBernhard R. Link, Nov 30, 2009
  3. Michael J GruberNov 30, 2009
  4. 2/7 add option to only visit the first parent of a equal tree mergeBernhard R. Link, Nov 30, 2009
  5. 3/7 format-patch defaults to --first-equal-tree-onlyBernhard R. Link, Nov 30, 2009
  6. 4/7 support equal tree merges in interactive rebaseBernhard R. Link, Nov 30, 2009
  7. 5/7 make rebase -m equal tree marker awareBernhard R. Link, Nov 30, 2009
  8. 6/7 add support for creating equal tree markers after rebaseBernhard R. Link, Nov 30, 2009
  9. 7/7 add support for creating equal tree markers to rebase -iBernhard R. Link, Nov 30, 2009
  10. Sverre RabbelierNov 30, 2009
  11. Paolo BonziniNov 30, 2009
  12. Bernhard R. LinkNov 30, 2009
  13. Michael J GruberNov 30, 2009
  14. Michael J GruberNov 30, 2009
  15. Bernhard R. LinkNov 30, 2009
  16. Johannes SchindelinNov 30, 2009
  17. Junio C HamanoNov 30, 2009
  18. Bernhard R. LinkNov 30, 2009
  19. Junio C HamanoDec 1, 2009
  20. Johannes SixtNov 30, 2009
  21. Junio C HamanoNov 30, 2009
  22. Nanako ShiraishiNov 30, 2009
  23. Junio C HamanoDec 1, 2009
  24. git-merge: a deprecation notice of the ancient command line syntaxJunio C Hamano, Dec 1, 2009
  25. Nicolas PitreDec 1, 2009
  26. Junio C HamanoDec 1, 2009
  27. Nanako ShiraishiDec 2, 2009
  28. Junio C HamanoDec 2, 2009
  29. Michael HaggertyDec 1, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.