Expand description
The service’s own retry of a push it stopped or that failed: the pauses, the waiting branches, the final failure.
What:
The service’s own retry of a push it stopped or that failed: the pause before each new try, the list of branches waiting
for one, and the test for the one failure no retry can mend.
Why:
The owner’s rule is that auto-push must land (SPEC.md, “Merges and commits never fail”). A push stopped by the stall
window, by the network, by an LFS server error or by a reference lock passes by itself, so the service tries again on its own,
with pauses that grow, until the push lands or a conflict needs the person. Nothing waits for the next commit: the work
loop is woken when the pause is over. The list is owned by the service’s work loop and kept on disk beside the instance’s
journal (push_retry_store.rs), so a restarted service rebuilds it; the person’s failure record is not the plan, since the
person’s next command shows it and removes it. A conflict, a login the service does not have and a hook on the server that
declined the push stop the retry until the next commit (owner decision, 2026-11-03).
In TS you’d write (pseudocode):
const pause = retries.schedule(item, attempt); /* later */ for (const due of retries.takeDue(gitDir)) await push(due);Structs§
- Due
- A push that is due again.
- Push
Retries - What:
The branches whose push is waiting for a new try, with the first pause.
Why:
The service loop alone owns it and changes it through
&mut self, so it needs no cell and no lock; workers get what is due as owned values (Retrying) and hand their changes back (RetryChange). - Retrying
- What: What the worker of one directory is handed about retries: the first pause (nothing when its handlers do not retry) and the pushes of that directory that are due again. Why: The plan belongs to the service loop alone. A worker never reads it: it gets its own copy of what is due for its directory, as an owned value inside its request, so no worker shares the plan with another and nothing waits for it.
Enums§
- Final
Failure - Why a failed push cannot pass by itself.
- Retry
Change - What: One change a worker asks of the plan: plan a try, or drop the plan of a branch. Why: A worker cannot change the plan (it does not hold it), so it returns what it did and the service loop applies the changes on its own thread, in the order they were made, which is how the last plan of a branch wins.
Constants§
- CONFLICT_
PHRASE - The words of the reconcile’s report of a conflict, the one failure that retrying cannot mend.
- FIRST_
PAUSE - The pause before the first new try when nothing configures it.
- HOOK_
DECLINED - The words every hook decline of Git’s own server side carries in the rejection’s reason:
"pre-receive hook declined"and"push-to-checkout hook declined"and"hook declined"(the update hook) inbuiltin/receive-pack.c, Git 2.56.0; a hosting service’s own reason that names a hook, such asprotected branch hook declined, ends the same way. - LOGIN_
PHRASES - The words with which Git and the programs it runs say that the remote wanted a login the push did not have, each from a
fixture run of
git pushfrom Git 2.56.0 on 2026-11-03: - LONGEST_
PAUSE - The longest pause between two tries: a push that keeps failing is tried about this often for as long as it fails.
- PLAN_
DIRECTORY - Directory, under the service instance’s journal, that holds the plan of the pushes waiting for a new try, so that a restarted service keeps trying them.
- REMOTE_
REJECTED - The mark of a line in which the server rejected one reference; Git prints it for every refused reference
(
transport.c,print_ref_status('!', "[remote rejected]", ...), Git 2.56.0). - RETRY_
VARIABLE - Environment variable that sets, in whole seconds, the pause before the first new try of a stopped push.
Functions§
- final_
failure - The failure of a push that no retry can mend, from Git’s own words; nothing for a failure that can pass (a stall, the network, a held lock) and for a rejection whose reason this release does not know.
- first_
pause_ from - What: The first pause for a value of the variable. Why: A missing, zero or malformed value falls back to the default, never to a tight loop.
- needs_
the_ person - Whether a failed push’s output says something stopped it that only the person can resolve.
- pause_
before - What:
The pause before try number
attempt(the first new try is number one): the first pause, doubled each time, never past the longest. Why: Short pauses mend a stall quickly; longer ones keep a host that is offline for an hour from being asked every few seconds. - plain_
words - What: The plain words the person’s failure record starts with for a failure that stops the retry, or nothing for a conflict, whose report already says what to do. Why: The owner’s decision is that a login failure and a server hook’s decline stop until the next commit (“Offline is retried, but auth and server hook declines stop until your next commit.”); the person is told which one it was, in words, above Git’s own.
- unrecognised_
rejection - The first line in which the server rejected the push for a reason this release does not know, or nothing: a push with such a line stays retried, and the journal names the line so that the reason can be learned.