fetch: only run 'gc' once when fetching multiple remotes

In multiple remotes mode, git-fetch is launched for n-1 remotes and the last remote is handled by the current process. Each of these processes will in turn run 'gc' at the end. This is not really a problem because even if multiple 'gc --auto' is run at the same time we still handle it correctly. It does show multiple "auto packing in the background" messages though. And we may waste some resources when gc actually runs because we still do some stuff before checking the lock and moving it to background. So let's try to avoid that. We should only need one 'gc' run after all objects and references are added anyway. Add a new option --no-auto-gc that will be used by those n-1 processes. 'gc --auto' will always run on the main fetch process (*). (*) even if we fetch remotes in parallel at some point in future, this should still be fine because we should "join" all those processes before this step. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Acked-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Jun 19, 2019 at 16:46 UTC c3d6b70338d0ac93f66142873f1606277dbe589f
3 files changed +20 -8
Documentation/fetch-options.txt
+4
@@ -88,6 +88,10 @@ ifndef::git-pull[]
88 Allow several <repository> and <group> arguments to be
89 specified. No <refspec>s may be specified.
90
91 +--[no-]auto-gc::
92 + Run `git gc --auto` at the end to perform garbage collection
93 + if needed. This is enabled by default.
94 +
95 -p::
96 --prune::
97 Before fetching, remove any remote-tracking references that no
builtin/fetch.c
+11 -6
@@ -48,6 +48,7 @@ static int prune_tags = -1; /* unspecified */
48
49 static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity, deepen_relative;
50 static int progress = -1;
51 +static int enable_auto_gc = 1;
52 static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen;
53 static int max_children = 1;
54 static enum transport_family family;
@@ -169,6 +170,8 @@ static struct option builtin_fetch_options[] = {
170 OPT_STRING_LIST(0, "negotiation-tip", &negotiation_tip, N_("revision"),
171 N_("report that we have only objects reachable from this object")),
172 OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
173 + OPT_BOOL(0, "auto-gc", &enable_auto_gc,
174 + N_("run 'gc --auto' after fetching")),
175 OPT_END()
176 };
177
@@ -1424,7 +1427,7 @@ static int fetch_multiple(struct string_list *list)
1427 return errcode;
1428 }
1429
1427 - argv_array_pushl(&argv, "fetch", "--append", NULL);
1430 + argv_array_pushl(&argv, "fetch", "--append", "--no-auto-gc", NULL);
1431 add_options_to_argv(&argv);
1432
1433 for (i = 0; i < list->nr; i++) {
@@ -1674,11 +1677,13 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
1677
1678 close_all_packs(the_repository->objects);
1679
1677 - argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL);
1678 - if (verbosity < 0)
1679 - argv_array_push(&argv_gc_auto, "--quiet");
1680 - run_command_v_opt(argv_gc_auto.argv, RUN_GIT_CMD);
1681 - argv_array_clear(&argv_gc_auto);
1680 + if (enable_auto_gc) {
1681 + argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL);
1682 + if (verbosity < 0)
1683 + argv_array_push(&argv_gc_auto, "--quiet");
1684 + run_command_v_opt(argv_gc_auto.argv, RUN_GIT_CMD);
1685 + argv_array_clear(&argv_gc_auto);
1686 + }
1687
1688 return result;
1689 }
t/t5514-fetch-multiple.sh
+5 -2
@@ -105,9 +105,12 @@ test_expect_success 'git fetch --multiple (two remotes)' '
105 git remote rm origin &&
106 git remote add one ../one &&
107 git remote add two ../two &&
108 - git fetch --multiple one two &&
108 + GIT_TRACE=1 git fetch --multiple one two 2>trace &&
109 git branch -r > output &&
110 - test_cmp ../expect output)
110 + test_cmp ../expect output &&
111 + grep "built-in: git gc" trace >gc &&
112 + test_line_count = 1 gc
113 + )
114 '
115
116 test_expect_success 'git fetch --multiple (bad remote names)' '