]> git.ipfire.org Git - thirdparty/git.git/commitdiff
commit-reach: guard !FIND_ALL early exit with generation ordering check
authorKristofer Karlsson <krka@spotify.com>
Mon, 29 Jun 2026 13:19:21 +0000 (13:19 +0000)
committerJunio C Hamano <gitster@pobox.com>
Mon, 29 Jun 2026 17:42:35 +0000 (10:42 -0700)
When paint_down_to_common() falls back to commit-date ordering (for
v1 commit graphs without corrected commit dates), the !FIND_ALL early
exit incorrectly fires.  The exit assumes the queue is generation-
ordered, so the first RESULT commit found must be the shallowest.
With date ordering this is not guaranteed: a closer merge base with
a lower committer date (clock skew) may still be in the queue behind
deeper commits.

Add a gen_ordered flag that is cleared when the date fallback fires,
and require it for the early exit.

Update the test from the previous commit to test_expect_success.

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
commit-reach.c
t/t6600-test-reach.sh

index 5a52be90a66f5a5b389f88cbc4cc35abf36ed244..ee4b7b692508cf34eb7d89eb6d9960c53b4e42ad 100644 (file)
@@ -59,11 +59,14 @@ static int paint_down_to_common(struct repository *r,
 {
        struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
        int i;
+       int gen_ordered = 1;
        timestamp_t last_gen = GENERATION_NUMBER_INFINITY;
        struct commit_list **tail = result;
 
-       if (!min_generation && !corrected_commit_dates_enabled(r))
+       if (!min_generation && !corrected_commit_dates_enabled(r)) {
                queue.compare = compare_commits_by_commit_date;
+               gen_ordered = 0;
+       }
 
        one->object.flags |= PARENT1;
        if (!n) {
@@ -98,11 +101,12 @@ static int paint_down_to_common(struct repository *r,
                                commit->object.flags |= RESULT;
                                tail = commit_list_append(commit, tail);
                                /*
-                                * The queue is generation-ordered; no
-                                * remaining common ancestor can be a
+                                * When the queue is generation-ordered,
+                                * no remaining common ancestor can be a
                                 * descendant of this one.
                                 */
                                if (!(mb_flags & MERGE_BASE_FIND_ALL) &&
+                                   gen_ordered &&
                                    generation < GENERATION_NUMBER_INFINITY)
                                        break;
                        }
index 601656fda655944fda394de8683439d518f2c958..3995ee0cbc849f8ae8019515b175753cd9d3f472 100755 (executable)
@@ -958,7 +958,7 @@ test_expect_success 'merge-base without --all is one of --all results' '
        grep -F -f single all
 '
 
-test_expect_failure 'merge-base without --all, clock skew, v1 commit-graph' '
+test_expect_success 'merge-base without --all, clock skew, v1 commit-graph' '
        git rev-parse skew-M2 >expect &&
        merge_base_all_modes skew-P1 skew-P2
 '