Git development
 help / color / mirror / Atom feed
* [PATCH] negotiator/skipping.c: parse parents before queueing
@ 2026-10-19 20:17 Taylor Blau
  2026-10-21  6:49 ` Patrick Steinhardt
  2026-10-22 21:21 ` [PATCH v2] " Taylor Blau
  0 siblings, 2 replies; 12+ messages in thread
From: Taylor Blau @ 2026-10-19 20:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Patrick Steinhardt, Elijah Newren,
	Jonathan Tan, René Scharfe, Derrick Stolee, Ted Nyman,
	Daniel Reynaud, Aaron Friel

From: Taylor Blau <ttaylorr@openai.com>

The skipping negotiator sorts its queue by commit date, but
`push_parent()` can add a parent before parsing it. Its date is still
zero, so old ref tips go ahead of it.

For example, suppose a topic branch is one commit ahead of master.
Skipping offers the topic tip and skips master's tip. Master's parent
then waits behind old ref tips. With enough old refs, negotiation can
end before we offer that recent common ancestor.

Parse each unseen parent before adding it to the queue, so the queue
uses its actual date. If parsing fails, leave the parent out of the
queue.

Signed-off-by: Taylor Blau <ttaylorr@openai.com>
---
 negotiator/skipping.c                |  5 ++++-
 t/t5552-skipping-fetch-negotiator.sh | 33 ++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/negotiator/skipping.c b/negotiator/skipping.c
index db90fa77b53..ed6e88b59b4 100644
--- a/negotiator/skipping.c
+++ b/negotiator/skipping.c
@@ -125,7 +125,7 @@ static void mark_common(struct data *data, struct commit *seen_commit)
  * entry has the correct flags and ttl.
  *
  * This function returns 1 if an entry was found or created, and 0 otherwise
- * (because the entry for this commit had already been popped).
+ * (because the commit could not be parsed or its entry had already been popped).
  */
 static int push_parent(struct data *data, struct entry *entry,
 		       struct commit *to_push)
@@ -151,6 +151,9 @@ static int push_parent(struct data *data, struct entry *entry,
 parent_found:
 		;
 	} else {
+		/* Parse the parent before using its date to order the queue. */
+		if (repo_parse_commit(the_repository, to_push))
+			return 0;
 		parent_entry = rev_list_push(data, to_push, 0);
 	}
 
diff --git a/t/t5552-skipping-fetch-negotiator.sh b/t/t5552-skipping-fetch-negotiator.sh
index 96e224168eb..7a0b9b32474 100755
--- a/t/t5552-skipping-fetch-negotiator.sh
+++ b/t/t5552-skipping-fetch-negotiator.sh
@@ -223,4 +223,37 @@ test_expect_success 'do not send "have" with ancestors of commits that server AC
 	have_sent b2.c1 b2.c0
 '
 
+test_expect_success 'recent ancestors are sent before old ref tips' '
+	rm -rf server client trace &&
+	git init server &&
+	test_tick=2000000000 &&
+	test_commit -C server --no-tag base &&
+	test_commit -C server --no-tag parent &&
+	test_commit -C server --no-tag main &&
+	git clone server client &&
+	test_commit -C server --no-tag to_fetch &&
+
+	git -C client checkout -b topic &&
+	test_commit -C client --no-tag topic &&
+
+	# These old tips have known dates, but the recent parent has no ref.
+	# Without parsing parents before queueing them, its date is zero and
+	# all of these tips are sent first, delaying it past the first batch.
+	for i in $(test_seq 32)
+	do
+		old=$(echo "old $i" |
+			GIT_AUTHOR_DATE="1000000000 +0000" \
+			GIT_COMMITTER_DATE="1000000000 +0000" \
+			git -C client commit-tree HEAD^{tree}) &&
+		git -C client update-ref refs/heads/old-$i "$old" || return 1
+	done &&
+
+	test_config -C client fetch.negotiationalgorithm skipping &&
+	trace_fetch client origin &&
+	git -C client rev-parse HEAD HEAD~2 >expect &&
+	sed -n "s/.*fetch> have //p" trace >haves &&
+	sed -n "1,2p" haves >actual &&
+	test_cmp expect actual
+'
+
 test_done

base-commit: c51408889c3b372814bc20b9431c3b74d0d268eb
-- 
2.56.0.187.gdc3dfa3647c

^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-10-24  2:06 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-19 20:17 [PATCH] negotiator/skipping.c: parse parents before queueing Taylor Blau
2026-10-21  6:49 ` Patrick Steinhardt
2026-10-21 19:02   ` Junio C Hamano
2026-10-22 20:38   ` Taylor Blau
2026-10-22 21:46     ` Junio C Hamano
2026-10-22 22:49       ` Taylor Blau
2026-10-22 21:21 ` [PATCH v2] " Taylor Blau
2026-10-22 22:34   ` Junio C Hamano
2026-10-22 22:48     ` Taylor Blau
2026-10-23 14:30       ` Junio C Hamano
2026-10-24  0:03         ` Taylor Blau
2026-10-24  2:06           ` Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox