summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/config/maintenance.adoc9
-rw-r--r--builtin/gc.c31
-rwxr-xr-xt/t7900-maintenance.sh20
3 files changed, 59 insertions, 1 deletions
diff --git a/Documentation/config/maintenance.adoc b/Documentation/config/maintenance.adoc
index b2bacdc822..d0c38f03fa 100644
--- a/Documentation/config/maintenance.adoc
+++ b/Documentation/config/maintenance.adoc
@@ -32,6 +32,15 @@ The possible strategies are:
strategy for scheduled maintenance.
* `gc`: This strategy runs the `gc` task. This is the default strategy for
manual maintenance.
+* `geometric`: This strategy performs geometric repacking of packfiles and
+ keeps auxiliary data structures up-to-date. The strategy expires data in the
+ reflog and removes worktrees that cannot be located anymore. When the
+ geometric repacking strategy would decide to do an all-into-one repack, then
+ the strategy generates a cruft pack for all unreachable objects. Objects that
+ are already part of a cruft pack will be expired.
++
+This repacking strategy is a full replacement for the `gc` strategy and is
+recommended for large repositories.
* `incremental`: This setting optimizes for performing small maintenance
activities that do not delete any data. This does not schedule the `gc`
task, but runs the `prefetch` and `commit-graph` tasks hourly, the
diff --git a/builtin/gc.c b/builtin/gc.c
index 8cab145009..19be3f87e1 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -1891,12 +1891,43 @@ static const struct maintenance_strategy incremental_strategy = {
},
};
+static const struct maintenance_strategy geometric_strategy = {
+ .tasks = {
+ [TASK_COMMIT_GRAPH] = {
+ .type = MAINTENANCE_TYPE_SCHEDULED | MAINTENANCE_TYPE_MANUAL,
+ .schedule = SCHEDULE_HOURLY,
+ },
+ [TASK_GEOMETRIC_REPACK] = {
+ .type = MAINTENANCE_TYPE_SCHEDULED | MAINTENANCE_TYPE_MANUAL,
+ .schedule = SCHEDULE_DAILY,
+ },
+ [TASK_PACK_REFS] = {
+ .type = MAINTENANCE_TYPE_SCHEDULED | MAINTENANCE_TYPE_MANUAL,
+ .schedule = SCHEDULE_DAILY,
+ },
+ [TASK_RERERE_GC] = {
+ .type = MAINTENANCE_TYPE_SCHEDULED | MAINTENANCE_TYPE_MANUAL,
+ .schedule = SCHEDULE_WEEKLY,
+ },
+ [TASK_REFLOG_EXPIRE] = {
+ .type = MAINTENANCE_TYPE_SCHEDULED | MAINTENANCE_TYPE_MANUAL,
+ .schedule = SCHEDULE_WEEKLY,
+ },
+ [TASK_WORKTREE_PRUNE] = {
+ .type = MAINTENANCE_TYPE_SCHEDULED | MAINTENANCE_TYPE_MANUAL,
+ .schedule = SCHEDULE_WEEKLY,
+ },
+ },
+};
+
static struct maintenance_strategy parse_maintenance_strategy(const char *name)
{
if (!strcasecmp(name, "incremental"))
return incremental_strategy;
if (!strcasecmp(name, "gc"))
return gc_strategy;
+ if (!strcasecmp(name, "geometric"))
+ return geometric_strategy;
die(_("unknown maintenance strategy: '%s'"), name);
}
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index 85e0cea4d9..0d76693fee 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -930,11 +930,29 @@ test_expect_success 'maintenance.strategy is respected' '
git gc --quiet --no-detach --skip-foreground-tasks
EOF
- test_strategy gc --schedule=weekly <<-\EOF
+ test_strategy gc --schedule=weekly <<-\EOF &&
git pack-refs --all --prune
git reflog expire --all
git gc --quiet --no-detach --skip-foreground-tasks
EOF
+
+ test_strategy geometric <<-\EOF &&
+ git pack-refs --all --prune
+ git reflog expire --all
+ git repack -d -l --geometric=2 --quiet --write-midx
+ git commit-graph write --split --reachable --no-progress
+ git worktree prune --expire 3.months.ago
+ git rerere gc
+ EOF
+
+ test_strategy geometric --schedule=weekly <<-\EOF
+ git pack-refs --all --prune
+ git reflog expire --all
+ git repack -d -l --geometric=2 --quiet --write-midx
+ git commit-graph write --split --reachable --no-progress
+ git worktree prune --expire 3.months.ago
+ git rerere gc
+ EOF
)
'