Skip to content

housekeeping: Don't prune recent objects (v14.8 backport)

When running git-gc(1), Git automatically executes git-prune(1) with a grace period of two weeks: only when objects are older than that grace period will they be pruned. This is really important to fix a race condition with concurrent commands, which all will first write new objects into the repository before making them reachable via a ref update. This means that there is a brief period between writing the new objects and making them reachable. If objects would be pruned without a grace period, it could kick in right before updating the references and thus cause repository corruption. The two-weeks grace period bridges this gap by giving enough head room to finish the transaction.

With the recent introduction of the heuristics-based OptimizeRepository RPC we have also started to use git-prune(1). The assumption was that the two-weeks grace period was the default of git-prune(1), but as it turns out it is only the default of git-gc(1). So because we are now running git-prune(1) without any parameters, we accidentally started to delete all unreachable objects, even if they had just been created.

Curiously, this bug only started to surface as we were migrating Rails to use OptimizeRepository. Seemingly, because we previously only were executing the RPC as part of our nightly job, the logic didn't trigger in the right moment and thus never caused any (known) problems. Still, this is a serious bug.

Fix this issue by passing --expire=two.weeks.ago to git-prune(1).

Changelog: fixed


v14.8 is the earliest release where we had the new logic, so no other releases are impacted.

Backports: !4410 (merged)

Merge request reports