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>

Kyle Zhao committed Jun 17, 2022 at 19:06 UTC 82f67ee13fb25ebed1cd722c83de49a1ac588429
4 files changed +35 -1
Documentation/config/push.txt
+5
@@ -137,3 +137,8 @@ push.negotiate::
137 server attempt to find commits in common. If "false", Git will
138 rely solely on the server's ref advertisement to find commits
139 in common.
140 +
141 +push.useBitmaps::
142 + If set to "false", disable use of bitmaps for "git push" even if
143 + `pack.useBitmaps` is "true", without preventing other git operations
144 + from using bitmaps. Default is true.
send-pack.c
+6
@@ -84,6 +84,8 @@ static int pack_objects(int fd, struct ref *refs, struct oid_array *advertised,
84 strvec_push(&po.args, "--progress");
85 if (is_repository_shallow(the_repository))
86 strvec_push(&po.args, "--shallow");
87 + if (args->disable_bitmaps)
88 + strvec_push(&po.args, "--no-use-bitmap-index");
89 po.in = -1;
90 po.out = args->stateless_rpc ? -1 : fd;
91 po.git_cmd = 1;
@@ -487,6 +489,7 @@ int send_pack(struct send_pack_args *args,
489 struct async demux;
490 const char *push_cert_nonce = NULL;
491 struct packet_reader reader;
492 + int use_bitmaps;
493
494 if (!remote_refs) {
495 fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
@@ -498,6 +501,9 @@ int send_pack(struct send_pack_args *args,
501 if (push_negotiate)
502 get_commons_through_negotiation(args->url, remote_refs, &commons);
503
504 + if (!git_config_get_bool("push.usebitmaps", &use_bitmaps))
505 + args->disable_bitmaps = !use_bitmaps;
506 +
507 git_config_get_bool("transfer.advertisesid", &advertise_sid);
508
509 /* Does the other end support the reporting? */
send-pack.h
+2 -1
@@ -26,7 +26,8 @@ struct send_pack_args {
26 /* One of the SEND_PACK_PUSH_CERT_* constants. */
27 push_cert:2,
28 stateless_rpc:1,
29 - atomic:1;
29 + atomic:1,
30 + disable_bitmaps:1;
31 const struct string_list *push_options;
32 };
33
t/t5516-fetch-push.sh
+22
@@ -1865,4 +1865,26 @@ test_expect_success 'push warns or fails when using username:password' '
1865 test_line_count = 1 warnings
1866 '
1867
1868 +test_expect_success 'push with config push.useBitmaps' '
1869 + mk_test testrepo heads/main &&
1870 + git checkout main &&
1871 + test_unconfig push.useBitmaps &&
1872 + GIT_TRACE2_EVENT="$PWD/default" \
1873 + git push testrepo main:test &&
1874 + test_subcommand git pack-objects --all-progress-implied --revs --stdout \
1875 + --thin --delta-base-offset -q <default &&
1876 +
1877 + test_config push.useBitmaps true &&
1878 + GIT_TRACE2_EVENT="$PWD/true" \
1879 + git push testrepo main:test2 &&
1880 + test_subcommand git pack-objects --all-progress-implied --revs --stdout \
1881 + --thin --delta-base-offset -q <true &&
1882 +
1883 + test_config push.useBitmaps false &&
1884 + GIT_TRACE2_EVENT="$PWD/false" \
1885 + git push testrepo main:test3 &&
1886 + test_subcommand git pack-objects --all-progress-implied --revs --stdout \
1887 + --thin --delta-base-offset -q --no-use-bitmap-index <false
1888 +'
1889 +
1890 test_done