Subject: Re: [PATCH 1/2] remote: defer repacking packed-refs when deleting refs

From: Junio C Hamano <[email-masked]>
Date: Tue, 20 May 2014 12:30:12 -0700

Jens Lindström <[email-masked]> writes:

> When 'git remote rm' or 'git remote prune' were used in a repository
> with many refs, and needed to delete many refs, a lot of time was spent
> deleting those refs since for each deleted ref, repack_without_refs()
> was called to rewrite packed-refs without just that deleted ref.
>
> To avoid this, defer the repacking until after all refs have been
> deleted (by delete_ref()), and then call repack_without_refs() once to
> repack without all the deleted refs.
>
> Signed-off-by: Jens Lindström <[email-masked]>
> ---
> This patch changes behavior when the operation is aborted in the
> middle, so that loose refs and ref logs might have been deleted, but
> not the corresponding entries in packed-refs, since packed-refs is now
> only updated at the end.

Also this makes it a bit more dangerous for processes accessing the
repository while pruning is in progress by exposing stale refs that
may be pointing at objects that are no longer present in the object
store in the packed-refs file for a longer period ("git fsck" may
fail, for example).

As long as we accept that removing a remote or pruning one are kinds
of "maintenance" operations and nobody else should be peeking into
the repository during maintenance period, it may be alright, but
aborting the operation in the middle will essentially leave the
repository in a corrupted state---the "abort corrupts" is a downside
with or without this change and is not a new problem.

A bit safer way to organize might be to first create a list of the
refs to be removed in-core, update packed-refs without these refs to
be removed, and then finally remove the loose ones, but I haven't
thought things through.