send-pack.c: add config push.useBitmaps

Reachability bitmaps are designed to speed up the "counting objects"
phase of generating a pack during a clone or fetch. They are not
optimized for Git clients sending a small topic branch via "git push".
In some cases (see [1]), using reachability bitmaps during "git push"
can cause significant performance regressions.

Add a new "push.useBitmaps" configuration variable to allow users to
tell "git push" not to use bitmaps. We already have "pack.bitmaps"
that controls the use of bitmaps, but a separate configuration variable
allows the reachability bitmaps to still be used in other areas,
such as "git upload-pack", while disabling it only for "git push".

[1]: https://lore.kernel.org/git/87zhoz8b9o.fsf@evledraar.gmail.com/

Signed-off-by: Kyle Zhao <kylezhao@tencent.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Kyle Zhao 2022-06-17 19:06:19 +00:00 committed by Junio C Hamano
parent 8168d5e9c2
commit 82f67ee13f
4 changed files with 35 additions and 1 deletions

View file

@ -137,3 +137,8 @@ push.negotiate::
server attempt to find commits in common. If "false", Git will server attempt to find commits in common. If "false", Git will
rely solely on the server's ref advertisement to find commits rely solely on the server's ref advertisement to find commits
in common. in common.
push.useBitmaps::
If set to "false", disable use of bitmaps for "git push" even if
`pack.useBitmaps` is "true", without preventing other git operations
from using bitmaps. Default is true.

View file

@ -84,6 +84,8 @@ static int pack_objects(int fd, struct ref *refs, struct oid_array *advertised,
strvec_push(&po.args, "--progress"); strvec_push(&po.args, "--progress");
if (is_repository_shallow(the_repository)) if (is_repository_shallow(the_repository))
strvec_push(&po.args, "--shallow"); strvec_push(&po.args, "--shallow");
if (args->disable_bitmaps)
strvec_push(&po.args, "--no-use-bitmap-index");
po.in = -1; po.in = -1;
po.out = args->stateless_rpc ? -1 : fd; po.out = args->stateless_rpc ? -1 : fd;
po.git_cmd = 1; po.git_cmd = 1;
@ -487,6 +489,7 @@ int send_pack(struct send_pack_args *args,
struct async demux; struct async demux;
const char *push_cert_nonce = NULL; const char *push_cert_nonce = NULL;
struct packet_reader reader; struct packet_reader reader;
int use_bitmaps;
if (!remote_refs) { if (!remote_refs) {
fprintf(stderr, "No refs in common and none specified; doing nothing.\n" fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
@ -498,6 +501,9 @@ int send_pack(struct send_pack_args *args,
if (push_negotiate) if (push_negotiate)
get_commons_through_negotiation(args->url, remote_refs, &commons); get_commons_through_negotiation(args->url, remote_refs, &commons);
if (!git_config_get_bool("push.usebitmaps", &use_bitmaps))
args->disable_bitmaps = !use_bitmaps;
git_config_get_bool("transfer.advertisesid", &advertise_sid); git_config_get_bool("transfer.advertisesid", &advertise_sid);
/* Does the other end support the reporting? */ /* Does the other end support the reporting? */

View file

@ -26,7 +26,8 @@ struct send_pack_args {
/* One of the SEND_PACK_PUSH_CERT_* constants. */ /* One of the SEND_PACK_PUSH_CERT_* constants. */
push_cert:2, push_cert:2,
stateless_rpc:1, stateless_rpc:1,
atomic:1; atomic:1,
disable_bitmaps:1;
const struct string_list *push_options; const struct string_list *push_options;
}; };

View file

@ -1865,4 +1865,26 @@ test_expect_success 'push warns or fails when using username:password' '
test_line_count = 1 warnings test_line_count = 1 warnings
' '
test_expect_success 'push with config push.useBitmaps' '
mk_test testrepo heads/main &&
git checkout main &&
test_unconfig push.useBitmaps &&
GIT_TRACE2_EVENT="$PWD/default" \
git push testrepo main:test &&
test_subcommand git pack-objects --all-progress-implied --revs --stdout \
--thin --delta-base-offset -q <default &&
test_config push.useBitmaps true &&
GIT_TRACE2_EVENT="$PWD/true" \
git push testrepo main:test2 &&
test_subcommand git pack-objects --all-progress-implied --revs --stdout \
--thin --delta-base-offset -q <true &&
test_config push.useBitmaps false &&
GIT_TRACE2_EVENT="$PWD/false" \
git push testrepo main:test3 &&
test_subcommand git pack-objects --all-progress-implied --revs --stdout \
--thin --delta-base-offset -q --no-use-bitmap-index <false
'
test_done test_done