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

[PATCH 4/5] Replace merge-base implementation

From
Daniel Barkalow <barkalow@iabervon.org>
Date
Apr 24, 2005, 00:18 UTC
Message-ID
<Pine.LNX.4.21.0504232016010.30848-100000@iabervon.org>
In-Reply-To
<Pine.LNX.4.21.0504231953490.30848-100000@iabervon.org>

The old implementation was a nice algorithm, but, unfortunately, it could be confused in some cases and would not necessarily do the obvious thing if one argument was decended from the other. This version fixes that by changing the criterion to the most recent common ancestor.

Signed-Off-By: Daniel Barkalow <barkalow@iabervon.org>
Index: merge-base.c
===================================================================
--- cae140a16189361d8c9f1f7e68ef519956fd26d9/merge-base.c  (mode:100644 sha1:ac1153bc5646cb2d515ff206b759f4a79e90273a)
+++ 9b75904eab1300d83264a1840d396160482fee88/merge-base.c  (mode:100644 sha1:0e4c58ede915aca5719bbd12ecd1945f2f300590)
@@ -5,67 +5,63 @@
 static struct commit *process_list(struct commit_list **list_p, int this_mark,
 				   int other_mark)
 {
-	struct commit_list *parent, *temp;
-	struct commit_list *posn = *list_p;
-	*list_p = NULL;
-	while (posn) {
-		parse_commit(posn->item);
-		if (posn->item->object.flags & this_mark) {
-			/*
-			  printf("%d already seen %s %x\n",
-			  this_mark
-			  sha1_to_hex(posn->parent->sha1),
-			  posn->parent->flags);
-			*/
-			/* do nothing; this indicates that this side
-			 * split and reformed, and we only need to
-			 * mark it once.
-			 */
-		} else if (posn->item->object.flags & other_mark) {
-			return posn->item;
-		} else {
-			/*
-			  printf("%d based on %s\n",
-			  this_mark,
-			  sha1_to_hex(posn->parent->sha1));
-			*/
-			posn->item->object.flags |= this_mark;
-			
-			parent = posn->item->parents;
-			while (parent) {
-				temp = malloc(sizeof(struct commit_list));
-				temp->next = *list_p;
-				temp->item = parent->item;
-				*list_p = temp;
-				parent = parent->next;
-			}
-		}
-		posn = posn->next;
+	struct commit *item = (*list_p)->item;
+	
+	if (item->object.flags & this_mark) {
+		/*
+		  printf("%d already seen %s %x\n",
+		  this_mark
+		  sha1_to_hex(posn->parent->sha1),
+		  posn->parent->flags);
+		*/
+		/* do nothing; this indicates that this side
+		 * split and reformed, and we only need to
+		 * mark it once.
+		 */
+		*list_p = (*list_p)->next;
+	} else if (item->object.flags & other_mark) {
+		return item;
+	} else {
+		/*
+		  printf("%d based on %s\n",
+		  this_mark,
+		  sha1_to_hex(posn->parent->sha1));
+		*/
+		pop_most_recent_commit(list_p);
+		item->object.flags |= this_mark;
 	}
 	return NULL;
 }
 
 struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
 {
-	struct commit_list *rev1list = malloc(sizeof(struct commit_list));
-	struct commit_list *rev2list = malloc(sizeof(struct commit_list));
+	struct commit_list *rev1list = NULL;
+	struct commit_list *rev2list = NULL;
 
-	rev1list->item = rev1;
-	rev1list->next = NULL;
+	commit_list_insert(rev1, &rev1list);
+	commit_list_insert(rev2, &rev2list);
 
-	rev2list->item = rev2;
-	rev2list->next = NULL;
+	parse_commit(rev1);
+	parse_commit(rev2);
 
 	while (rev1list || rev2list) {
 		struct commit *ret;
-		ret = process_list(&rev1list, 0x1, 0x2);
-		if (ret) {
-			/* XXXX free lists */
-			return ret;
+		if (!rev1list) {
+			// process 2
+			ret = process_list(&rev2list, 0x2, 0x1);
+		} else if (!rev2list) {
+			// process 1
+			ret = process_list(&rev1list, 0x1, 0x2);
+		} else if (rev1list->item->date < rev2list->item->date) {
+			// process 2
+			ret = process_list(&rev2list, 0x2, 0x1);
+		} else {
+			// process 1
+			ret = process_list(&rev1list, 0x1, 0x2);
 		}
-		ret = process_list(&rev2list, 0x2, 0x1);
 		if (ret) {
-			/* XXXX free lists */
+			free_commit_list(rev1list);
+			free_commit_list(rev2list);
 			return ret;
 		}
 	}
Previous: Daniel BarkalowNext: Daniel Barkalow
Message 11 of 12 in “Better merge-base, alternative transport programs”
  1. 0/5 Better merge-base, alternative transport programsDaniel Barkalow, Apr 24, 2005
  2. 1/5 Add some functions for commit listsDaniel Barkalow, Apr 24, 2005
  3. Linus TorvaldsApr 24, 2005
  4. Linus TorvaldsApr 24, 2005
  5. Daniel BarkalowApr 24, 2005
  6. Allow multiple date-ordered listsDaniel Barkalow, Apr 24, 2005
  7. Add -u option to diff-cache to show UNCHANGED filesAndreas Gal, Apr 24, 2005
  8. Petr BaudisApr 24, 2005
  9. 2/5 Parse tree objects completelyDaniel Barkalow, Apr 24, 2005
  10. 3/5 Additional functions for the objects databaseDaniel Barkalow, Apr 24, 2005
  11. 4/5 Replace merge-base implementationDaniel Barkalow, Apr 24, 2005
  12. 5/5 Various transport programsDaniel Barkalow, Apr 24, 2005

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.