]> git.ipfire.org Git - thirdparty/git.git/commitdiff
midx: disable replace objects
authorXing Xin <xingxin.xx@bytedance.com>
Mon, 8 Apr 2024 05:26:57 +0000 (05:26 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 17 Apr 2024 19:35:41 +0000 (12:35 -0700)
We observed a series of clone failures arose in a specific set of
repositories after we fully enabled the MIDX bitmap feature within our
Codebase service. These failures were accompanied with error messages
such as:

    Cloning into bare repository 'clone.git'...
    remote: Enumerating objects: 8, done.
    remote: Total 8 (delta 0), reused 0 (delta 0), pack-reused 8 (from 1)
    Receiving objects: 100% (8/8), done.
    fatal: did not receive expected object ...
    fatal: fetch-pack: invalid index-pack output

Temporarily disabling the MIDX feature eliminated the reported issues.
After some investigation we found that all repositories experiencing
failures contain replace references, which seem to be improperly
acknowledged by the MIDX bitmap generation logic.

A more thorough explanation about the root cause from Taylor Blau says:

Indeed, the pack-bitmap-write machinery does not itself call
disable_replace_refs(). So when it generates a reachability bitmap, it
is doing so with the replace refs in mind. You can see that this is
indeed the cause of the problem by looking at the output of an
instrumented version of Git that indicates what bits are being set
during the bitmap generation phase.

With replace refs (incorrectly) enabled, we get:

    [2, 4, 6, 8, 13, 3, 6, 7, 3, 4, 6, 8]

and doing the same after calling disable_replace_refs(), we instead get:

    [2, 5, 6, 13, 3, 6, 7, 3, 4, 6, 8]

Single pack bitmaps are unaffected by this issue because we generate
them from within pack-objects, which does call disable_replace_refs().

This patch updates the MIDX logic to disable replace objects within the
multi-pack-index builtin, and a test showing a clone (which would fail
with MIDX bitmap) is added to demonstrate the bug.

Helped-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Xing Xin <xingxin.xx@bytedance.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/multi-pack-index.c
t/t5326-multi-pack-bitmaps.sh

index a72aebecaa2f3aa96f802b635b4d55c5f122d56c..8360932d2e75577dbb416c5851d33556d3688233 100644 (file)
@@ -8,6 +8,7 @@
 #include "strbuf.h"
 #include "trace2.h"
 #include "object-store-ll.h"
+#include "replace-object.h"
 
 #define BUILTIN_MIDX_WRITE_USAGE \
        N_("git multi-pack-index [<options>] write [--preferred-pack=<pack>]" \
@@ -273,6 +274,8 @@ int cmd_multi_pack_index(int argc, const char **argv,
        };
        struct option *options = parse_options_concat(builtin_multi_pack_index_options, common_opts);
 
+       disable_replace_refs();
+
        git_config(git_default_config, NULL);
 
        if (the_repository &&
index 70d1b58709a91199bf6d589e141897ca96204547..1fb3b0f9d7ac11ee3e873f7845e837f21a154bc0 100755 (executable)
@@ -434,6 +434,27 @@ test_expect_success 'tagged commits are selected for bitmapping' '
        )
 '
 
+test_expect_success 'do not follow replace objects for MIDX bitmap' '
+       rm -fr repo &&
+       git init repo &&
+       test_when_finished "rm -fr repo" &&
+       (
+               cd repo &&
+
+               test_commit A &&
+               test_commit B &&
+               git checkout --orphan=orphan A &&
+               test_commit orphan &&
+
+               git replace A HEAD &&
+               git repack -ad --write-midx --write-bitmap-index &&
+
+               # generating reachability bitmaps with replace refs
+               # enabled will result in broken clones
+               git clone --no-local --bare . clone.git
+       )
+'
+
 corrupt_file () {
        chmod a+w "$1" &&
        printf "bogus" | dd of="$1" bs=1 seek="12" conv=notrunc