builtin/maintenance: make "gc" strategy accessible

While the user can pick the "incremental" maintenance strategy, it is not possible to explicitly use the "gc" strategy. This has two downsides: - It is impossible to use the default "gc" strategy for a specific repository when the strategy was globally set to a different strategy. - It is not possible to use git-gc(1) for scheduled maintenance. Address these issues by making making the "gc" strategy configurable. Furthermore, extend the strategy so that git-gc(1) runs for both manual and scheduled maintenance. Signed-off-by: Patrick Steinhardt <ps@pks.im> Acked-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Oct 24, 2025 at 08:57 UTC 40a74158337f9154d26f82aa7923ca281ae131c2
3 files changed +21 -4
Documentation/config/maintenance.adoc
+2
@@ -30,6 +30,8 @@ The possible strategies are:
30 +
31 * `none`: This strategy implies no tasks are run at all. This is the default
32 strategy for scheduled maintenance.
33 +* `gc`: This strategy runs the `gc` task. This is the default strategy for
34 + manual maintenance.
35 * `incremental`: This setting optimizes for performing small maintenance
36 activities that do not delete any data. This does not schedule the `gc`
37 task, but runs the `prefetch` and `commit-graph` tasks hourly, the
builtin/gc.c
+6 -3
@@ -1843,10 +1843,11 @@ struct maintenance_strategy {
1843
1844 static const struct maintenance_strategy none_strategy = { 0 };
1845
1846 -static const struct maintenance_strategy default_strategy = {
1846 +static const struct maintenance_strategy gc_strategy = {
1847 .tasks = {
1848 [TASK_GC] = {
1849 - .type = MAINTENANCE_TYPE_MANUAL,
1849 + .type = MAINTENANCE_TYPE_MANUAL | MAINTENANCE_TYPE_SCHEDULED,
1850 + .schedule = SCHEDULE_DAILY,
1851 },
1852 },
1853 };
@@ -1894,6 +1895,8 @@ static struct maintenance_strategy parse_maintenance_strategy(const char *name)
1895 {
1896 if (!strcasecmp(name, "incremental"))
1897 return incremental_strategy;
1898 + if (!strcasecmp(name, "gc"))
1899 + return gc_strategy;
1900 die(_("unknown maintenance strategy: '%s'"), name);
1901 }
1902
@@ -1937,7 +1940,7 @@ static void initialize_task_config(struct maintenance_run_opts *opts,
1940 strategy = none_strategy;
1941 type = MAINTENANCE_TYPE_SCHEDULED;
1942 } else {
1940 - strategy = default_strategy;
1943 + strategy = gc_strategy;
1944 type = MAINTENANCE_TYPE_MANUAL;
1945 }
1946
t/t7900-maintenance.sh
+13 -1
@@ -915,7 +915,7 @@ test_expect_success 'maintenance.strategy is respected' '
915 git gc --quiet --no-detach --skip-foreground-tasks
916 EOF
917
918 - test_strategy incremental --schedule=weekly <<-\EOF
918 + test_strategy incremental --schedule=weekly <<-\EOF &&
919 git pack-refs --all --prune
920 git prune-packed --quiet
921 git multi-pack-index write --no-progress
@@ -923,6 +923,18 @@ test_expect_success 'maintenance.strategy is respected' '
923 git multi-pack-index repack --no-progress --batch-size=1
924 git commit-graph write --split --reachable --no-progress
925 EOF
926 +
927 + test_strategy gc <<-\EOF &&
928 + git pack-refs --all --prune
929 + git reflog expire --all
930 + git gc --quiet --no-detach --skip-foreground-tasks
931 + EOF
932 +
933 + test_strategy gc --schedule=weekly <<-\EOF
934 + git pack-refs --all --prune
935 + git reflog expire --all
936 + git gc --quiet --no-detach --skip-foreground-tasks
937 + EOF
938 )
939 '
940