]> git.ipfire.org Git - thirdparty/git.git/commitdiff
t6099, t6600: add side-exhaustion regression tests
authorKristofer Karlsson <krka@spotify.com>
Sat, 11 Jul 2026 13:27:39 +0000 (13:27 +0000)
committerJunio C Hamano <gitster@pobox.com>
Sat, 11 Jul 2026 21:00:11 +0000 (14:00 -0700)
Add t6099 to test the case where multiple merge-base candidates exist
and one is an ancestor of another. This exercises the side-exhaustion
optimization in paint_down_to_common together with the
remove_redundant safety net in get_merge_bases_many_0.

Add a mixed finite/INFINITY test to t6600 where one tip is outside
the commit-graph (INFINITY generation) and the other is inside.
This exercises the region transition: the walk starts in the
INFINITY region where side-exhaustion is disabled, then crosses
into the finite region where it can fire.

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
t/meson.build
t/t6099-merge-base-side-exhaustion.sh [new file with mode: 0755]

index 7c3c070426dc9ec7188469cf67ae7e56a2df39f5..727c93d78192cb99f426e5555653f425f249a8e3 100644 (file)
@@ -788,6 +788,7 @@ integration_tests = [
   't6041-bisect-submodule.sh',
   't6050-replace.sh',
   't6060-merge-index.sh',
+  't6099-merge-base-side-exhaustion.sh',
   't6100-rev-list-in-order.sh',
   't6101-rev-parse-parents.sh',
   't6102-rev-list-unexpected-objects.sh',
diff --git a/t/t6099-merge-base-side-exhaustion.sh b/t/t6099-merge-base-side-exhaustion.sh
new file mode 100755 (executable)
index 0000000..4f1e0d5
--- /dev/null
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+test_description='merge-base with ancestor among merge-base candidates
+
+Test that merge-base --all correctly handles cases where
+multiple merge-base candidates exist and one is an ancestor
+of another. The side-exhaustion optimization in
+paint_down_to_common may exit before STALE propagation
+removes the ancestor, but remove_redundant catches it.
+
+Graph shape (parents are below children):
+
+   A ----------- X
+   |\           /|
+   | B---------/ |
+   | |           |
+   e2 \         f2
+   |   |         |
+   e1 d1        f1
+    \  |        /
+     \ |       /
+      \|      /
+       C
+
+A and X are the two tips.
+B and C are both reachable from A and X.
+B reaches C through d1.
+Only B should appear in merge-base --all output.
+'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+test_expect_success 'setup ancestor merge-base candidate' '
+       test_commit C &&
+
+       git checkout -b d-chain HEAD &&
+       test_commit d1 &&
+       test_commit B &&
+
+       git checkout -b e-path C &&
+       test_commit e1 &&
+       test_commit e2 &&
+
+       git checkout -b f-path C &&
+       test_commit f1 &&
+       test_commit f2 &&
+
+       git checkout -b branch-A e-path &&
+       test_merge A B &&
+
+       git checkout -b branch-X f-path &&
+       test_merge X B &&
+
+       git commit-graph write --reachable
+'
+
+test_expect_success 'merge-base --all excludes ancestor candidate' '
+       git rev-parse B >expected &&
+       git merge-base --all A X >actual &&
+       test_cmp expected actual
+'
+
+test_expect_success 'merge-base (single) finds shallowest' '
+       git rev-parse B >expected &&
+       git merge-base A X >actual &&
+       test_cmp expected actual
+'
+
+# Without commit-graph: generation numbers are INFINITY,
+# side-exhaustion optimization does not fire.
+test_expect_success 'merge-base --all without commit-graph' '
+       rm -f .git/objects/info/commit-graph &&
+       git rev-parse B >expected &&
+       git merge-base --all A X >actual &&
+       test_cmp expected actual
+'
+
+test_done