If a force push or branch deletion occurs, the old object that the ref pointed to may cease to be referenced by any ref and thereby be eligible for garbage collection.
In the duration of the git post-receive hook of such a push, is the old object guaranteed to still be valid?
If a force push or branch deletion occurs, the old object that the ref pointed to may cease to be referenced by any ref and thereby be eligible for garbage collection.
In the duration of the git post-receive hook of such a push, is the old object guaranteed to still be valid?
Share Improve this question asked yesterday Runxi YuRunxi Yu 3312 silver badges9 bronze badges 9 | Show 4 more comments2 Answers
Reset to default 5I think the point made by @j6t is correct: I don't think there is a formal guarantee.
That being said: the code tries to be explicit about it.
You may look at the implementation of the server-side receive-pack
action (code from v2.48.1):
int cmd_receive_pack(int argc, // l.2503
...) {
[...]
run_receive_hook(commands, "post-receive", 1, // l.2610
&push_options);
[...]
if (auto_gc) { // l.2615
struct child_process proc = CHILD_PROCESS_INIT;
if (prepare_auto_maintenance(1, &proc)) {
[...]
and note that the execution of the post-receive
hook (l.2610) happens before an explicit call to the "auto_gc" action (code block starting at l.2615).
So if your post-receive
hook is synchronous, this autogc action will not delete obsolete commits before running your hook.
git
also has a basic locking mechanism on its database to prevent concurrent actions to do bad things, so I think other gc actions would be rejected during the execution of your hook (I haven't brought evidence of this point in this answer though).
There is no formal guarantee that the dangling object remains valid, because it is impossible to know when a post-receive hook (or any git
command for that matter) has completed their operation.
The only provision that exists is that garbage collection will give objects a "short lease of life" after they become dangling. "Short" here means two weeks and is configurable. The intent is that this time span will be enough for any ongoing git
command to complete and to have stopped using the dangling objects.
gc
in the Git docs. The only bit of information that slightly says whengit gc
is triggered is the following part fromgit gc
docs: "When common porcelain operations that create objects are run, they will check whether the repository has grown substantially since the last maintenance, and if so run git gc automatically." Force push or branch deletion do not create objects (blobs, trees, commits, or tags), they only update or delete refs. – dani-vta Commented 23 hours ago