[PATCH v2 3/8] repack: retain cruft packs in MIDXs after incremental repacks
- From
Taylor Blau <ttaylorr@openai.com>
- Date
- Oct 1, 2026, 04:11 UTC
- Message-ID
- <a244b26030ca2387e6feb768f849626540091624.1790827875.git.me@ttaylorr.com>
- In-Reply-To
- <cover.1790827875.git.me@ttaylorr.com>
An incremental repack can write a commit and tree into a new pack while leaving objects they reach in an existing cruft pack. For example, a commit can make a previously unreachable blob reachable again. Since 'repack' will invoke 'pack-objects' with '--incremental', it will not copy the blob out of its cruft pack.
When the 'repack.midxMustContainCruft' configuration is set to "false", writing the first MIDX after such a repack may omit that cruft pack. The new pack bypasses the `!names.nr` fallback, and there are no previous MIDX packs for `midx_has_unknown_packs()` to check. Selecting the new commit for bitmap coverage then fails because its reachable objects are not all in the MIDX.
The omission dates all the way back to 5ee86c273bf (repack: exclude cruft pack(s) from the MIDX where possible, 2025-06-23). It relies on geometric repacking to copy once-cruft objects with '--stdin-packs=follow'. However, an ordinary incremental repack makes no such guarantee. Require the MIDX to include cruft packs in that case, even when a new pack was written.
This fixes ordinary '--write-midx'. The separate '--write-midx=incremental' writer does not consult this flag and needs its own handling.
Exercise this with the existing fixture that makes a cruft commit reachable again and adds a new (unpacked) commit on top, and ensure that the incremental repack is able to successfully write a reachability bitmap.
Signed-off-by: Taylor Blau <ttaylorr@openai.com> --- builtin/repack.c | 6 ++++++ t/t7704-repack-cruft.sh | 11 +++++++++++ 2 files changed, 17 insertions(+)
diff --git a/builtin/repack.c b/builtin/repack.c index c4360382c1f..b7596d488da 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -539,6 +539,12 @@ int cmd_repack(int argc, strvec_push(&cmd.args, "--stdin-packs=follow"); strvec_push(&cmd.args, "--unpacked"); } else { + /* + * Incremental repacks do not copy already-packed objects, + * so cruft packs may be required to form a reachability + * closure for the MIDX. + */ + midx_must_contain_cruft = 1; strvec_push(&cmd.args, "--unpacked"); strvec_push(&cmd.args, "--incremental"); } diff --git a/t/t7704-repack-cruft.sh b/t/t7704-repack-cruft.sh index b49f22878f7..f7f83e70ffe 100755 --- a/t/t7704-repack-cruft.sh +++ b/t/t7704-repack-cruft.sh @@ -787,6 +787,17 @@ test_expect_success 'geometric repack rescues descendants of loose trees' ' ) ' +test_expect_success 'incremental repack includes cruft for MIDX bitmaps' ' + setup_cruft_exclude_tests incremental-cruft && + ( + cd incremental-cruft && + + GIT_TEST_MULTI_PACK_INDEX=0 \ + git repack -d --write-midx --write-bitmap-index && + git rev-list --test-bitmap HEAD + ) +' + test_expect_success 'repack --write-midx includes cruft when instructed' ' setup_cruft_exclude_tests exclude-cruft-when-instructed && (
-- 2.56.0.8.ga42f775cbe2