git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <junkio@cox.net>
To: Linus Torvalds <torvalds@osdl.org>
Cc: git@vger.kernel.org
Subject: merge-base: fully contaminate the well.
Date: Thu, 10 Nov 2005 18:58:07 -0800	[thread overview]
Message-ID: <7vzmobuc00.fsf@assigned-by-dhcp.cox.net> (raw)
In-Reply-To: Pine.LNX.4.64.0511091348530.4627@g5.osdl.org

The discussion on the list demonstrated a pathological case where
an ancestor of a merge-base can be left interesting.  This commit
introduces a postprocessing phase to fix it.

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

  Linus Torvalds <torvalds@osdl.org> writes:

  > On Wed, 9 Nov 2005, Junio C Hamano wrote:
  >
  >> But the point of well-poisoning you did in merge-base was to
  >> detect that E is an ancestor of B and exclude it in the first
  >> place.
  >
  > Ahh, you're right, and I'm wrong. That "E" is not a real merge-base, since 
  > there _is_ a valid merge-base that is a direct descendant of it and thus 
  > objectively better.
  >
  > Which means that sometimes it can stop with too _many_ merge heads, just 
  > because it hasn't realized that they are reachable through a chain that is 
  > otherwise provably uninteresting.

  I am not particularly proud of this change, but here is an
  attempt to fully contaminate the well without going all the
  way down to root.  It adds a postprocessing phase which does
  not parse any new commits.

  > The thing is, I don't see what guarantees that the show-branch brhaviour 
  > is safe or conservative.

  You are right about this; I have a separate patch to fix it.


 merge-base.c |   78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 77 insertions(+), 1 deletions(-)

applies-to: 8eacf17303188e55375f76bea8051555ba1baf02
a2fd94f707128f3f390362725c8d8b0802940111
diff --git a/merge-base.c b/merge-base.c
index 286bf0e..43a6818 100644
--- a/merge-base.c
+++ b/merge-base.c
@@ -80,6 +80,45 @@ static struct commit *interesting(struct
  * Now, list does not have any interesting commit.  So we find the newest
  * commit from the result list that is not marked uninteresting.  Which is
  * commit B.
+ *
+ *
+ * Another pathological example how this thing can fail to mark an ancestor
+ * of a merge base as UNINTERESTING without the postprocessing phase.
+ *
+ *		  2
+ *		  H
+ *	    1    / \
+ *	    G   A   \
+ *	    |\ /     \ 
+ *	    | B       \
+ *	    |  \       \
+ *	     \  C       F
+ *	      \  \     / 
+ *	       \  D   /   
+ *		\ |  /
+ *		 \| /
+ *		  E
+ *
+ *	 list			A B C D E F G H
+ *	 G1 H2			- - - - - - 1 2
+ *	 H2 E1 B1		- 1 - - 1 - 1 2
+ *	 F2 E1 B1 A2		2 1 - - 1 2 1 2
+ *	 E3 B1 A2		2 1 - - 3 2 1 2
+ *	 B1 A2			2 1 - - 3 2 1 2
+ *	 C1 A2			2 1 1 - 3 2 1 2
+ *	 D1 A2			2 1 1 1 3 2 1 2
+ *	 A2			2 1 1 1 3 2 1 2
+ *	 B3			2 3 1 1 3 2 1 2
+ *	 C7			2 3 7 1 3 2 1 2
+ *
+ * At this point, unfortunately, everybody in the list is
+ * uninteresting, so we fail to complete the following two
+ * steps to fully marking uninteresting commits.
+ *
+ *	 D7			2 3 7 7 3 2 1 2
+ *	 E7			2 3 7 7 7 2 1 2
+ *
+ * and we end up showing E as an interesting merge base.
  */
 
 static int show_all = 0;
@@ -88,6 +127,7 @@ static int merge_base(struct commit *rev
 {
 	struct commit_list *list = NULL;
 	struct commit_list *result = NULL;
+	struct commit_list *tmp = NULL;
 
 	if (rev1 == rev2) {
 		printf("%s\n", sha1_to_hex(rev1->object.sha1));
@@ -104,9 +144,10 @@ static int merge_base(struct commit *rev
 
 	while (interesting(list)) {
 		struct commit *commit = list->item;
-		struct commit_list *tmp = list, *parents;
+		struct commit_list *parents;
 		int flags = commit->object.flags & 7;
 
+		tmp = list;
 		list = list->next;
 		free(tmp);
 		if (flags == 3) {
@@ -130,6 +171,41 @@ static int merge_base(struct commit *rev
 	if (!result)
 		return 1;
 
+	/*
+	 * Postprocess to fully contaminate the well.
+	 */
+	for (tmp = result; tmp; tmp = tmp->next) {
+		struct commit *c = tmp->item;
+		/* Reinject uninteresting ones to list,
+		 * so we can scan their parents.
+		 */
+		if (c->object.flags & UNINTERESTING)
+			commit_list_insert(c, &list);
+	}
+	while (list) {
+		struct commit *c = list->item;
+		struct commit_list *parents;
+
+		tmp = list;
+		list = list->next;
+		free(tmp);
+
+		/* Anything taken out of the list is uninteresting, so
+		 * mark all its parents uninteresting.  We do not
+		 * parse new ones (we already parsed all the relevant
+		 * ones).
+		 */
+		parents = c->parents;
+		while (parents) {
+			struct commit *p = parents->item;
+			parents = parents->next;
+			if (!(p->object.flags & UNINTERESTING)) {
+				p->object.flags |= UNINTERESTING;
+				commit_list_insert(p, &list);
+			}
+		}
+	}
+
 	while (result) {
 		struct commit *commit = result->item;
 		result = result->next;
---
0.99.9.GIT

  parent reply	other threads:[~2005-11-11  2:58 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-11-07 16:48 Comments on recursive merge Linus Torvalds
2005-11-07 16:56 ` Linus Torvalds
2005-11-07 23:19   ` [PATCH] merge-recursive: Only print relevant rename messages Fredrik Kuivinen
2005-11-07 23:54     ` Junio C Hamano
2005-11-09 10:36       ` Fredrik Kuivinen
2005-11-07 22:58 ` Comments on recursive merge Fredrik Kuivinen
2005-11-08  0:13   ` Junio C Hamano
2005-11-08  0:33     ` Linus Torvalds
2005-11-08  0:59       ` Junio C Hamano
2005-11-08 11:58       ` Johannes Schindelin
2005-11-08 21:02         ` Fredrik Kuivinen
2005-11-08 21:47           ` Junio C Hamano
2005-11-08 21:52           ` Linus Torvalds
2005-11-08 22:36             ` Fredrik Kuivinen
2005-11-08 23:05               ` Linus Torvalds
2005-11-08 23:18                 ` Johannes Schindelin
2005-11-09  0:18                   ` Linus Torvalds
2005-11-09  6:10                     ` Junio C Hamano
2005-11-09  0:32                 ` Petr Baudis
2005-11-09  0:51                   ` Linus Torvalds
2005-11-09  0:59                     ` Junio C Hamano
2005-11-09  1:22                       ` Linus Torvalds
2005-11-09  1:42                         ` Junio C Hamano
2005-11-09 10:20                           ` Junio C Hamano
2005-11-09 14:59                             ` Petr Baudis
2005-11-09 16:30                             ` Linus Torvalds
2005-11-09 20:13                               ` Junio C Hamano
2005-11-09 21:58                                 ` Linus Torvalds
2005-11-09 22:56                                   ` Junio C Hamano
2005-11-09 23:34                                     ` Linus Torvalds
2005-11-11  2:58                                   ` Junio C Hamano [this message]
2005-11-11  5:36                                     ` merge-base: fully contaminate the well Linus Torvalds
2005-11-11  6:04                                       ` Junio C Hamano
2005-11-11 16:18                                         ` Linus Torvalds
2005-11-11  8:28                                       ` Junio C Hamano
2005-11-08 23:04           ` Comments on recursive merge Johannes Schindelin
2005-11-08 16:21       ` [RFC/PATCH] Make git-recursive the default strategy for git-pull Junio C Hamano
2005-11-11 22:25       ` Comments on recursive merge Junio C Hamano
2005-11-11 22:53         ` Linus Torvalds
2005-11-12  0:42           ` Junio C Hamano
2005-11-12  6:35         ` Ryan Anderson
2005-11-12  7:44           ` [PATCH] GIT commit statistics Junio C Hamano
2005-11-12 12:19             ` Martin Langhoff
2005-11-12 12:53               ` Petr Baudis
2005-11-15 10:04                 ` Catalin Marinas
2005-11-15 15:29                   ` Chuck Lever
2005-11-12 19:04               ` Johannes Schindelin
2005-11-13 10:59               ` Junio C Hamano
2005-11-13 20:42                 ` Martin Langhoff
2005-11-14  3:33                   ` Junio C Hamano
2005-11-14  4:01                     ` Martin Langhoff
2005-11-14  6:06                       ` Junio C Hamano
2005-11-14  8:51                         ` Martin Langhoff
2005-11-14  9:25                           ` Petr Baudis
2005-11-14 21:25                             ` Martin Langhoff
2005-11-14  9:27                           ` Junio C Hamano
2005-11-15  3:00                           ` Junio C Hamano
2005-11-13 11:11               ` Petr Baudis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7vzmobuc00.fsf@assigned-by-dhcp.cox.net \
    --to=junkio@cox.net \
    --cc=git@vger.kernel.org \
    --cc=torvalds@osdl.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).