t5333: demonstrate various pseudo-merge bugs

Using the test helper introduced via the previous commit, add various failing tests demonstrating bugs in the pseudo-merge implementation. These are all marked as failing with one exception. The "sampleRate=0" test describes a latent bug, which is only reachable through a code path that is itself masked by a separate bug. A future commit will fix that bug, and, in turn, cause the aforementioned test to fail. Accordingly, that commit will mark the test as failing, and it will be re-marked as passing in a separate commit which fixes the once-latent bug. For the rest: the following commits will explain and fix the underlying bugs in detail. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed May 11, 2026 at 20:46 UTC 49369d8290c3a5c95d835df85fdf53eba7562496
1 file changed +198
t/t5333-pseudo-merge-bitmaps.sh
+198
@@ -462,4 +462,202 @@ test_expect_success 'use pseudo-merge in boundary traversal' '
462 )
463 '
464
465 +test_expect_failure 'apply pseudo-merges during fill-in traversal' '
466 + test_when_finished "rm -fr pseudo-merge-fill-in-traversal" &&
467 + git init pseudo-merge-fill-in-traversal &&
468 + (
469 + cd pseudo-merge-fill-in-traversal &&
470 +
471 + git config bitmapPseudoMerge.test.pattern refs/tags/ &&
472 + git config bitmapPseudoMerge.test.maxMerges 1 &&
473 + git config bitmapPseudoMerge.test.stableThreshold never &&
474 +
475 + test_commit_bulk 64 &&
476 + tag_everything &&
477 + git repack -ad &&
478 +
479 + pack=$(ls .git/objects/pack/pack-*.pack) &&
480 + git rev-parse HEAD~63 >in &&
481 + test-tool bitmap write "$(basename $pack)" <in &&
482 +
483 + test_pseudo_merges >merges &&
484 + test_line_count = 1 merges &&
485 +
486 + test_commit stale &&
487 +
488 + git rev-list --count --objects HEAD >expect &&
489 +
490 + : >trace2.txt &&
491 + GIT_TRACE2_EVENT=$PWD/trace2.txt \
492 + git rev-list --count --objects --use-bitmap-index HEAD >actual &&
493 + test_pseudo_merges_satisfied 1 <trace2.txt &&
494 +
495 + test_cmp expect actual
496 + )
497 +'
498 +
499 +test_expect_failure 'apply pseudo-merges from multiple groups during fill-in' '
500 + test_when_finished "rm -fr pseudo-merge-fill-in-multi" &&
501 + git init pseudo-merge-fill-in-multi &&
502 + (
503 + cd pseudo-merge-fill-in-multi &&
504 +
505 + test_commit base &&
506 + base=$(git rev-parse HEAD) &&
507 +
508 + for side in left right
509 + do
510 + git checkout -B $side base &&
511 +
512 + test_commit_bulk --id=$side 64 &&
513 + git rev-list --no-object-names HEAD --not $base >in &&
514 + while read oid
515 + do
516 + echo "create refs/group-$side/$oid $oid" || return 1
517 + done <in | git update-ref --stdin || return 1
518 + done &&
519 +
520 + git checkout left &&
521 + git merge right &&
522 + git repack -ad &&
523 +
524 + git config bitmapPseudoMerge.left.pattern "refs/group-left/" &&
525 + git config bitmapPseudoMerge.left.maxMerges 1 &&
526 + git config bitmapPseudoMerge.left.stableThreshold never &&
527 +
528 + git config bitmapPseudoMerge.right.pattern "refs/group-right/" &&
529 + git config bitmapPseudoMerge.right.maxMerges 1 &&
530 + git config bitmapPseudoMerge.right.stableThreshold never &&
531 +
532 + pack="$(ls .git/objects/pack/pack-*.pack)" &&
533 + git rev-parse "$base" >in &&
534 + test-tool bitmap write "$(basename $pack)" <in &&
535 +
536 + test_pseudo_merges >merges &&
537 + test_line_count = 2 merges &&
538 +
539 + test_commit stale &&
540 +
541 + git rev-list --count --objects HEAD >expect &&
542 +
543 + : >trace2.txt &&
544 + GIT_TRACE2_EVENT=$PWD/trace2.txt \
545 + git rev-list --count --objects --use-bitmap-index HEAD >actual &&
546 + test_pseudo_merges_satisfied 2 <trace2.txt &&
547 +
548 + test_cmp expect actual
549 + )
550 +'
551 +
552 +test_expect_failure 'apply pseudo-merges with overlapping groups during fill-in' '
553 + test_when_finished "rm -fr pseudo-merge-fill-in-overlap" &&
554 + git init pseudo-merge-fill-in-overlap &&
555 + (
556 + cd pseudo-merge-fill-in-overlap &&
557 +
558 + test_commit_bulk 64 &&
559 + tag_everything &&
560 + git repack -ad &&
561 +
562 + pack="$(ls .git/objects/pack/pack-*.pack)" &&
563 +
564 + # Use two pseudo-merge group patterns that both match
565 + # refs/tags/, so every tagged commit belongs to both
566 + # groups. This exercises the extended lookup table
567 + # path in apply_pseudo_merges_for_commit().
568 + git config bitmapPseudoMerge.all.pattern "refs/tags/" &&
569 + git config bitmapPseudoMerge.all.maxMerges 1 &&
570 + git config bitmapPseudoMerge.all.stableThreshold never &&
571 +
572 + git config bitmapPseudoMerge.tags.pattern "refs/tags/" &&
573 + git config bitmapPseudoMerge.tags.maxMerges 1 &&
574 + git config bitmapPseudoMerge.tags.stableThreshold never &&
575 +
576 + git rev-parse HEAD~63 >in &&
577 + test-tool bitmap write "$(basename $pack)" <in &&
578 +
579 + test_pseudo_merges >merges &&
580 + test_line_count = 2 merges &&
581 +
582 + test_commit stale &&
583 +
584 + git rev-list --count --objects HEAD >expect &&
585 +
586 + : >trace2.txt &&
587 + GIT_TRACE2_EVENT=$PWD/trace2.txt \
588 + git rev-list --count --objects --use-bitmap-index HEAD >actual &&
589 + test_pseudo_merges_satisfied 2 <trace2.txt &&
590 +
591 + test_cmp expect actual
592 + )
593 +'
594 +
595 +test_expect_failure 'pseudo-merge commits are correctly classified by date' '
596 + test_when_finished "rm -fr pseudo-merge-date-classification" &&
597 + git init pseudo-merge-date-classification &&
598 + (
599 + cd pseudo-merge-date-classification &&
600 +
601 + test_commit_bulk 64 &&
602 + tag_everything &&
603 + git repack -ad &&
604 +
605 + pack="$(ls .git/objects/pack/pack-*.pack)" &&
606 +
607 + # Configure two pseudo-merge groups: one that only
608 + # matches "stable" refs (older than one month), and one
609 + # that matches all refs. With 64 freshly-created tags
610 + # (all younger than one month) the stable group should
611 + # have zero pseudo-merges and the catch-all group should
612 + # have one.
613 + #
614 + # Use GIT_TEST_DATE_NOW to align "now" (and therefore
615 + # "1.month.ago") with the test_tick timestamps so that
616 + # the commits are within the last month.
617 + #
618 + # This exercises the date-based classification in
619 + # find_pseudo_merge_group_for_ref(), which requires
620 + # that commits are parsed before inspecting their date.
621 + git config bitmapPseudoMerge.stable.pattern "refs/tags/" &&
622 + git config bitmapPseudoMerge.stable.maxMerges 64 &&
623 + git config bitmapPseudoMerge.stable.stableThreshold never &&
624 + git config bitmapPseudoMerge.stable.threshold 1.month.ago &&
625 +
626 + git config bitmapPseudoMerge.all.pattern "refs/tags/" &&
627 + git config bitmapPseudoMerge.all.maxMerges 1 &&
628 + git config bitmapPseudoMerge.all.stableThreshold never &&
629 + git config bitmapPseudoMerge.all.threshold now &&
630 +
631 + git rev-parse HEAD~63 >in &&
632 + GIT_TEST_DATE_NOW=$test_tick \
633 + test-tool bitmap write "$(basename $pack)" <in &&
634 +
635 + test_pseudo_merges >merges &&
636 + test_line_count = 1 merges
637 + )
638 +'
639 +
640 +test_expect_success 'sampleRate=0 does not cause division by zero' '
641 + test_when_finished "rm -fr pseudo-merge-sample-rate-zero" &&
642 + git init pseudo-merge-sample-rate-zero &&
643 + (
644 + cd pseudo-merge-sample-rate-zero &&
645 +
646 + test_commit_bulk 64 &&
647 + tag_everything &&
648 + git repack -ad &&
649 +
650 + pack="$(ls .git/objects/pack/pack-*.pack)" &&
651 +
652 + git config bitmapPseudoMerge.test.pattern "refs/tags/" &&
653 + git config bitmapPseudoMerge.test.maxMerges 1 &&
654 + git config bitmapPseudoMerge.test.sampleRate 0 &&
655 + git config bitmapPseudoMerge.test.threshold now &&
656 + git config bitmapPseudoMerge.test.stableThreshold never &&
657 +
658 + git rev-parse HEAD~63 >in &&
659 + test-tool bitmap write "$(basename $pack)" <in
660 + )
661 +'
662 +
663 test_done