t6099, t6600: add side-exhaustion regression tests
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>
Kristofer Karlsson committed
Jul 11, 2026 at 13:27 UTC
0789dc8f046c017e1dc69bb720a7b425aa8a1292
2 files changed
+83
t/meson.build
+1
@@ -788,6 +788,7 @@ integration_tests = [
788
't6041-bisect-submodule.sh',
789
't6050-replace.sh',
790
't6060-merge-index.sh',
791
+ 't6099-merge-base-side-exhaustion.sh',
792
't6100-rev-list-in-order.sh',
793
't6101-rev-parse-parents.sh',
794
't6102-rev-list-unexpected-objects.sh',
t/t6099-merge-base-side-exhaustion.sh
new
+82
@@ -0,0 +1,82 @@
1
+#!/bin/sh
2
+
3
+test_description='merge-base with ancestor among merge-base candidates
4
+
5
+Test that merge-base --all correctly handles cases where
6
+multiple merge-base candidates exist and one is an ancestor
7
+of another. The side-exhaustion optimization in
8
+paint_down_to_common may exit before STALE propagation
9
+removes the ancestor, but remove_redundant catches it.
10
+
11
+Graph shape (parents are below children):
12
+
13
+ A ----------- X
14
+ |\ /|
15
+ | B---------/ |
16
+ | | |
17
+ e2 \ f2
18
+ | | |
19
+ e1 d1 f1
20
+ \ | /
21
+ \ | /
22
+ \| /
23
+ C
24
+
25
+A and X are the two tips.
26
+B and C are both reachable from A and X.
27
+B reaches C through d1.
28
+Only B should appear in merge-base --all output.
29
+'
30
+
31
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
32
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
33
+
34
+TEST_PASSES_SANITIZE_LEAK=true
35
+. ./test-lib.sh
36
+
37
+test_expect_success 'setup ancestor merge-base candidate' '
38
+ test_commit C &&
39
+
40
+ git checkout -b d-chain HEAD &&
41
+ test_commit d1 &&
42
+ test_commit B &&
43
+
44
+ git checkout -b e-path C &&
45
+ test_commit e1 &&
46
+ test_commit e2 &&
47
+
48
+ git checkout -b f-path C &&
49
+ test_commit f1 &&
50
+ test_commit f2 &&
51
+
52
+ git checkout -b branch-A e-path &&
53
+ test_merge A B &&
54
+
55
+ git checkout -b branch-X f-path &&
56
+ test_merge X B &&
57
+
58
+ git commit-graph write --reachable
59
+'
60
+
61
+test_expect_success 'merge-base --all excludes ancestor candidate' '
62
+ git rev-parse B >expected &&
63
+ git merge-base --all A X >actual &&
64
+ test_cmp expected actual
65
+'
66
+
67
+test_expect_success 'merge-base (single) finds shallowest' '
68
+ git rev-parse B >expected &&
69
+ git merge-base A X >actual &&
70
+ test_cmp expected actual
71
+'
72
+
73
+# Without commit-graph: generation numbers are INFINITY,
74
+# side-exhaustion optimization does not fire.
75
+test_expect_success 'merge-base --all without commit-graph' '
76
+ rm -f .git/objects/info/commit-graph &&
77
+ git rev-parse B >expected &&
78
+ git merge-base --all A X >actual &&
79
+ test_cmp expected actual
80
+'
81
+
82
+test_done