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

[PATCH] rev-list: skip bitmap traversal for --left-right

From
Jeff King <peff@peff.net>
Date
Nov 1, 2024, 12:16 UTC
Message-ID
<20241101121606.GA2327410@coredump.intra.peff.net>
Running:
  git rev-list --left-right --use-bitmap-index one...two

will produce output without any left-right markers, since the bitmap traversal returns only a single set of reachable commits. Instead we should refuse to use bitmaps here and produce the correct output using a traditional traversal.

This is probably not the only remaining option that misbehaves with bitmaps, but it's particularly egregious in that it feels like it _could_ work. Doing two separate traversals for the left/right sides and then taking the symmetric set differences should yield the correct answer, but our traversal code doesn't know how to do that.

It's not clear if naively doing two separate traversals would always be a performance win. A traditional traversal only needs to walk down to the merge base, but bitmaps always fill out the full reachability set. So depending on your bitmap coverage, we could end up walking old bits of history twice to fill out the same uninteresting bits on both sides. We'd also of course end up with a very large --boundary set, if the user asked for that.

So this might or might not be something worth implementing later. But for now, let's make sure we don't produce the wrong answer if somebody tries it.

The test covers this, but also the same thing with "--count" (which is what I originally tried in a real-world case). Ironically the try_bitmap_count() code already realizes that "--left-right" won't work there. But that just causes us to fall back to the regular bitmap traversal code, which itself doesn't handle counting (we produce a list of objects rather than a count).

Signed-off-by: Jeff King <peff@peff.net>
---
 builtin/rev-list.c      |  7 +++++++
 t/t5310-pack-bitmaps.sh | 12 ++++++++++++
 2 files changed, 19 insertions(+)
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index f62bcbf2b1..3078787115 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -485,6 +485,13 @@ static int try_bitmap_traversal(struct rev_info *revs,
 	if (revs->max_count >= 0)
 		return -1;
 
+	/*
+	 * We can't know which commits were left/right in a single traversal,
+	 * and we don't yet know how to traverse them separately.
+	 */
+	if (revs->left_right)
+		return -1;
+
 	bitmap_git = prepare_bitmap_walk(revs, filter_provided_objects);
 	if (!bitmap_git)
 		return -1;
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index 7044c7d7c6..6bcbea64cc 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -503,6 +503,18 @@ test_expect_success 'boundary-based traversal is used when requested' '
 	done
 '
 
+test_expect_success 'left-right not confused by bitmap index' '
+	git rev-list --left-right other...HEAD >expect &&
+	git rev-list --use-bitmap-index --left-right other...HEAD >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'left-right count not confused by bitmap-index' '
+	git rev-list --left-right --count other...HEAD >expect &&
+	git rev-list --use-bitmap-index --left-right --count other...HEAD >actual &&
+	test_cmp expect actual
+'
+
 test_bitmap_cases "pack.writeBitmapLookupTable"
 
 test_expect_success 'verify writing bitmap lookup table when enabled' '
-- 
2.47.0.441.g1a09955689
Next: Taylor Blau
Message 1 of 6 in “rev-list: skip bitmap traversal for --left-right”
  1. rev-list: skip bitmap traversal for --left-rightJeff King, Nov 1, 2024
  2. Taylor BlauNov 1, 2024
  3. Jeff KingNov 4, 2024
  4. Jeff KingNov 4, 2024
  5. Taylor BlauNov 4, 2024
  6. Ayush ChandekarFeb 2, 2025

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.