Skip to main content

Module landing

Module landing 

Source
Expand description

What the commit service does to land a commit: the serialized step, the index lock hold, preparation, replay and after-commit work. What: What the commit service does to land a commit: the serialized step, the index lock hold, preparation, replay and after-commit work. Why: The landing is the service’s core and changes together.

In TS you’d write (pseudocode):

// landing/index.ts: one `export * from './file'` per module below.

Modules§

claim_time
The clocks a claim’s lease is judged by. What: A reading of the clocks a claim’s lease is judged by: the machine and the boot the host is in, the host’s monotonic clock, and the wall clock. Two readings of one boot are compared by the monotonic clock; a reading of an earlier boot of the same machine is past at once; the wall clock judges every other pair. Why: A lease must run out when its holder stopped, not when somebody sets the date. The wall clock steps (a time sync, a person, a virtual machine resuming), and a step forward made a live holder look an hour stale while a step back kept a dead holder’s claim alive. CLOCK_MONOTONIC is one clock for every process of a host, never steps, and does not count a suspended host’s sleep, so a holder and a recoverer on one boot agree on how long a claim went unrenewed. It restarts at every boot, so a reading carries the boot ID (/proc/sys/kernel/random/boot_id). A restart ends the holder, so a claim of an earlier boot has run out at once, and a wall clock set back at boot cannot strand it. That holds only when both readings are of one machine: two hosts that share a work directory have unrelated boot IDs, and the other host’s boot is not the end of its holder. So a reading also carries the machine ID (/etc/machine-id), and a different boot ID is evidence of a restart only beside an equal, known machine ID. Equal non-empty boot IDs still compare by the monotonic clock. Where either reading has no boot ID, only the wall clock is left to compare; where either has no machine ID, a different boot ID proves no restart, so the wall clock judges that pair as the fallback. Machines cloned with one machine ID cannot be told apart; their claims are judged as one machine’s.
landed_summary
The one summary line a landed commit prints, with the abbreviated name Git would print. What: The one summary line a landed commit prints, the way git commit prints it: [<branch> <name>] <subject>, with (root-commit) for a commit without a parent and detached HEAD for a detached head, the name abbreviated as Git abbreviates it. Why: The line is for a commit the service built itself, where no git commit ran to print one. It is printed once, after the service moved the branch, so the name is the commit that landed; a commit that real Git builds prints Git’s own summary, because the wrapper adds no --quiet to it. The abbreviation honors core.abbrev and otherwise follows the size of the repository (object_abbreviation.rs), and Git is asked only when the configuration or the object store is not something that reader models.
landing_location
The landing location a forwarded index writer coordinates with: the real index and the registry. What: Where a forwarded command’s real index lives: one git rev-parse that reports the git directory and the index Git would use. Why: An index writer waits for the commit service’s hold on the real index. A command outside a repository, or one writing another index, waits for nothing (src/index-lock/landing-location.ts).
maintenance_decision
Automatic maintenance decision: config record parsing and the enable and detach rules. What: The decision behind automatic maintenance after a landing: parsing git config --null --get-regexp records, and choosing whether git maintenance run --auto runs and whether it detaches. Why: Native git commit runs this step after updating HEAD; a landing replaces that commit with plumbing, so the pack count grows by one per commit unless this step runs. The rules mirror Git’s prepare_auto_maintenance in run-command.c, including JavaScript number semantics for values the incumbent reads with Number(...).
maintenance_run
Running automatic maintenance after a landing: the config read, then git maintenance run --auto. What: Running automatic maintenance after a landing: one git config read for the maintenance keys (or the commit’s configuration snapshot), then git maintenance run --auto, detached or not, in the real worktree, with Git’s words kept in the journal. Its exit status is returned for the caller to ignore, as native Git does. Why: A landing writes its objects with git fast-import, which leaves them loose when the batch holds at most fastimport.unpackLimit objects (100 by default; Git 2.56.0 builtin/fast-import.c, end_packfile) and keeps one pack otherwise; without this step the loose objects and packs accumulate and every later Git process searches them all. Failures are logged and never fail the landed commit.
service_amend
What an amend takes from the commit it replaces: parents, message and author. What: The facts of the commit an amend replaces, read once from the repository: its parents, its first parent’s tree, its author and its message, and the author line an amend makes of them. Why: An amend keeps the parents of the commit it replaces, keeps its message when no message option is given and keeps its author unless the command line says otherwise. All of that is arithmetic on the replaced commit’s own record, so the wrapper embeds it; each rule is compared field by field with native git commit --amend in binary_service_amend_tests.rs. A commit with a header the amend would have to carry (another encoding, a merge tag) returns nothing and native Git handles the line.
service_built_checks
What a commit Git built adds to the branch, answered from the object store without starting Git. What: The two questions the landing asks about a commit that Git built (a signed commit), answered from the object store without starting Git: which parents the commit has, and whether every object it adds to the branch is present. Why: Each question was a git rev-list start (about five milliseconds warm, more when the host has evicted the Git executable) on the wait of every signed commit. A commit that has the branch tip as its only parent adds only the objects that differ from the tip’s tree, which a walk of the two trees finds by reading the directories that changed. Only a proof is taken from here: whatever the walk cannot show (a repository with replacement objects, grafts or a shallow history, a commit with another header, an object that looks missing) is left to the rev-list the landing always ran, so a refusal is Git’s.
service_captures
The service’s memory of when the bytes of the commits it landed were captured, per worktree. What: The service’s memory of when the bytes of the commits it landed were captured, kept per worktree. Why: Two commands that capture a file from one worktree at different moments hold different states of it, and the later capture holds everything the earlier one did (doc/decision/cli-git-concurrent-commits.md, “Serial landing”). When the service sends a commit back because a landed commit changed the same path, the client needs to know which of the two captured later, and only the service saw the landed commit’s request. The stamp is a reading of CLOCK_MONOTONIC, one clock for every process of the host, so captures made by different wrapper processes compare. The memory lives in the service process and starts empty with it, so a restart can only make a capture unknown, never misordered: a commit with no entry is treated as captured by somebody else, and the client then merges instead of preferring either side. A reboot restarts both the clock and the service together. Entries are kept per worktree, because the rule holds for captures of one worktree only.
service_claim_renewal
The renewal that keeps the claims of a shared work directory from looking abandoned while their holder works. What: Keeps the lease of the claims one service instance holds fresh while it works, so a claim is taken over only when its holder stopped, never because its holder is slow, and tells the holder when its claim was taken over anyway. Why: A claim’s lease starts at the clock reading in its file name and the other instances run a claim again once the lease ran out. A push can take longer than any fixed lease, and an item can wait behind other claimed work; a claim that is never renewed would make both look abandoned. A holder that dies stops renewing, so its claims still expire, and no lock file is involved: the claim’s file name is the whole protocol. A renewal renames the claim from the name the renewal last wrote, so it can only reach its own claim, and a claim that was taken over is found gone instead of being renewed or settled on another instance’s behalf. Claim kept: the lease stays because a killed holder’s claims are recognised as abandoned only by their reading (no process identity or lock file is involved), and because the linked worktrees of a bare repository drain one common directory. No lock is held in the process either. The renewal thread is the one owner of the claims’ current names (the drain never renames a claim except to settle it); the drain tells the thread of a claim it takes over a channel, and the two share only atomic flags per claim. A settlement finds the claim’s file by its id and generation, which a renewal never changes, and asks again when a renewal renamed the file between the look and the rename, so neither side ever waits for the other.
service_commit
The commit command’s path through the commit service. What: The commit command’s path through the resident service: prepare the commit in this process (private index, policies), send the prepared change to the service, and report what it landed. Why: The service is the only writer, so a commit takes no lock and polls nothing: preparation and policies run here, outside the service’s serialized step, and the service moves the branch once for a whole batch of commits (doc/planning/cli-git-resident-service.md, “Where preparation and policies run”). Every command line lands through it. The lines service_commit_args.rs accepts are built here from the command line (message and identity options, sign-off, trailers, a reused or fixup message, -a, an index commit, --amend); every other line, and every commit that is not on an ordinary branch with an ordinary state, is built by real Git in a scratch repository and landed as Git made it. Which route a commit takes is decided by service_route.rs; what is prepared is service_prepare.rs.
service_commit_args
Which commit command lines the commit service covers, and the message they stand for. What: Which git commit command lines the resident service lands, and the message such a line stands for. Why: The service lands the scoped commit an agent or a person types most (git commit -m <message> -- <paths>), with the options that only shape the message or the identity: -F <file>, --author, --date, --trailer, --cleanup, --allow-empty-message, -s, --amend and --reset-author. Every other option (editor, signing, templates) still goes through the transaction until the service covers it, so this module answers “is this line one the service covers” before anything is prepared, and builds the message with the clean-up Git applies when no editor opens.
service_durable
Where the landing’s own syncs wait: queued for a background thread when the landing publishes, made before return otherwise. What: Where the landing’s own syncs wait: not on the path the person waits on, unless the landing publishes nothing. Why: The owner’s rule for the commit protocol, 2026-11-03: “Force at leaving, else background”: no forced write while the person waits, so a power cut loses that attempt exactly as it does with native Git (staged changes and files are intact, the commit is run again), and whatever the command already promised when it left (an error, a withdrawal, a hand-over) was forced to disk first. A landing that publishes a commit therefore only queues the syncs of its records (the intent, the lock marker, the completion record, the done mark and the directory syncs); one background thread makes them in batches, each batch overlapped. A landing that publishes nothing syncs what it wrote before it returns. Git’s own object, reference and index writes follow core.fsync as they do for native Git: the in-process index writer flushes only when core.fsync names the index (ConfigSnapshot::hardens_index). Nothing here changes what a killed process leaves: the page cache keeps every write whether or not it was synced.
service_handoff
The wrapper’s side of after-commit work: records and the wake. What: The wrapper’s side of after-commit work: leave the push and upkeep records for a commit the service landed and wake the service. Why: The commit returns as soon as it is saved. The push (which can take as long as the network does) and the upkeep run in the service afterwards; a push that fails is reported by the person’s next wrapper command (push_failure_notice.rs) (doc/planning/cli-git-resident-service.md, “After-commit work”). The wrapper starts no program and waits for no one: it writes whole files and sends one message.
service_head
Whether a worktree’s head still names the branch a commit was prepared on. What: Whether a worktree’s head still names the branch a commit was prepared on. Why: Native git commit updates HEAD, so a worktree that switched branches while the commit waited (in the editor, for a signature) fails with “cannot lock ref ‘HEAD’” and changes nothing. The service moves the named branch itself, so it asks the same question before anything moves: a branch moved under a worktree that is on another branch would leave that worktree’s index describing the wrong commit. The answer is read from the worktree’s HEAD file when that file can be trusted and from Git otherwise, so an ordinary landing starts no extra Git.
service_hold_retry
A forwarded index writer started again when the commit service took the index before its Git did. What: Runs a forwarded index writer again when real Git lost the race for the index to the commit service, instead of showing the person Git’s refusal. Why: The wait for the service’s hold ends when the hold is released, but the service may take the index again for the next landing before the writer’s own Git has started (a burst of commits lands one batch after another), and Git then ends with its refusal to create the index lock. For the few commands that take that lock before they change anything and read no standard input, running them again once the service lets go is the same command the person typed. The refusal is kept in a file while this can happen and is shown only when it is final, so a transient loss is never printed. Every other command, and a lock that a foreign program holds, keep the behavior of native Git.
service_index_attempts
The attempts and the wait of an acquisition of the index lock. What: The attempts and the wait of an acquisition of index.lock: placement tried again after each wake, a dead service’s lock reclaimed at once, a holder proven alive and an owner nothing proves alive both waited for on the watch with no bound, polled for where no watch can be set, a dead holder reported at once, and the notices that name the holder. Why: The wait blocks on an inotify watch set before the first attempt, so a release between an attempt and the wait is not missed; the only timer is the repetition of the holder’s line, and a poll where no watch can be set. The module is split from service_index_lock.rs, which holds the acquisition’s entry points and the lock itself.
service_index_claim
The claim chain that keeps two reclaimers apart where the file system gives no flock. What: The claim chain: how one reclaimer at a time is chosen to remove a stale index lock, using only files placed whole beside the lock and the judgement of whether their makers are gone. Every reclaim goes through it, on every file system. Why: A removal by name removes whatever the name holds by then, so two reclaimers of one stale file must not both go on to unlink it (the second would remove the live lock a landing placed after the first). A flock on the stale file would do where the file system gives one, but a reclaimer on that path and one on the claim path would not see each other, and a lock manager can answer one call and refuse the next; one mechanism for all reclaimers closes that. The exclusion is a numbered chain of claim files named from the stale lock’s marker. A reclaimer places its claim at the lowest slot whose claims below it are all made by gone processes, and holds only when it finds every slot below its own still there and gone. A dead claimer’s claim is never removed while the stale file stands at its name, because removing a claim by name would be the same race one level down; claims are added, a reclaimer removes its own live claim only when it backs off, and every claim is removed after the stale file left its name, when nothing destructive is left to guard (doc/planning/cli-git-one-reclaimer-per-index.md, “The claim chain”). A claim whose maker is on another machine is neither passed over nor waited for as a running one: it stays and the person is told.
service_index_found
What an acquisition of the index lock found when it had to wait, for the service’s log. What: What an acquisition of the index lock found when it had to wait: the marker on the lock, how old the lock is, whether the holder it names is gone, running or unknown, and which processes have the lock open; the notes an acquisition keeps for the service’s log. Why: A commit that waited five seconds for the index lock left a log that said how long and not for whom. The description is built only after a placement found the lock held, so the fast path of an acquisition pays nothing for it; the scan of /proc/*/fd for the processes that have the lock open is made once, at the first look.
service_index_hold
The service’s hold on a placed index lock: the check that it is still the holder’s, the release and the removal. What: The service’s hold on one index lock after it is placed: the check that the lock is still the holder’s, the release that installs the new index, and the removal of a lock that is not released. Why: A holder removes its lock by path, so it first asks whether the path still names the file it placed (service_index_ownership.rs). A question that cannot be answered is neither answer: the lock stays, the failure is said in the log, and the service ends after its batch so that the restart reclaims the lock. The module is split from service_index_lock.rs, which re-exports IndexLock.
service_index_identity
Who a marker’s holder is: the identity a process writes, and the answers a reader gives (gone, running, unknown). What: Who a marker’s holder is: the identity this process writes into a marker, and the three answers a reader gives about a holder named in one: gone, running, or unknown. Why: A marker names a process by its PID and start tick, which mean something only in the boot and the PID namespace they were read in. The identity therefore ends in the boot ID and the PID namespace, a writer whose /proc numbers processes differently from the process itself writes none, and a reader that cannot compare like with like answers unknown, which keeps the lock and proves nothing, instead of reading a number of another namespace as a local process and calling a live service gone. The module is split from service_index_marker.rs, which re-exports the public items here under their old names.
service_index_lock
The commit service’s hold on Git’s index lock across a landing. What: The service’s hold on Git’s own index.lock across a landing: taken first, by exclusive creation, waited for without polling when another program holds it, and released by moving the new index over the real one. Why: Git’s own commit takes the index lock before it moves the branch and gives it up after the index is written. A landing that moved the branch first and took the lock afterwards left the index showing content a landed commit had replaced for as long as a foreign git held the lock, and a commit prepared from that index could land a revert. The wait for a foreign holder is event-driven: an inotify watch on the Git directory wakes the service when the lock itself is removed or moved away, and the only timer is the repetition of the holder’s notice. On platforms without inotify a held lock fails at once with the plain message. The lock carries a marker with the batch number and the holding process from the moment it exists until it is removed after the new index is in place, so a restart can tell its own stale lock from a foreign one wherever the service was killed, and never takes over a lock whose holder still runs (doc/planning/cli-git-resident-service.md, “Landing every command line”). The marker, the inotify watch, the placement of the marked file, and the attempts and the wait are in service_index_marker.rs, service_index_watch.rs, service_index_placement.rs and service_index_attempts.rs, and are re-exported here under the names callers use.
service_index_marker
The marker the service writes into the index lock and the questions asked of a marker. What: The marker the service writes into the index.lock it holds, and the questions asked of a marker found there. Why: A restart tells its own stale lock from a foreign one, and a live holder from a dead one, by the marker alone: the batch, the holding process and that process’s birth identity. The module is split from service_index_lock.rs, which re-exports the public items here under their old names.
service_index_ownership
Whether the index lock is still the file the holder placed, and the record of a lock that could not be settled. What: Whether the file at the path of an index lock is still the file this holder placed there, and the record that a lock could not be settled. Why: A holder releases or removes its lock by path. The staging file’s descriptor is kept open for as long as the hold lasts, so the inode it names cannot be freed and numbered again, and asking whether the path still names it needs a stat and a pread, never a new descriptor. A check that opened the lock by path failed with EMFILE exactly when the service was out of descriptors, and a failed check was read as “another program’s lock”, which left a lock naming the live service behind. A question that cannot be answered is neither answer: the lock is kept and the service ends after its batch, so that the restart reclaims it.
service_index_placement
How the service’s marked file becomes the index lock, and the cleanup of staging files. What: How the service puts its marked file in place as index.lock: the system calls it makes, the atomic placement itself, and the removal of a stale lock. Why: The lock must never exist without its marker, so the marker is written to a file that is new and then made the lock in one step (a rename that does not replace, else a hard link). The calls are one Platform value so a control can refuse or count them for one acquisition alone. The module is split from service_index_lock.rs, which re-exports the public items here under their old names; the staging files are in service_index_staging.rs.
service_index_prestage
The marker of the next batch’s index lock, made and flushed while the service is idle. What: The marker of the next batch’s index lock, created, written and flushed to storage while the service is idle, so that a commit’s lock path only places it. Why: The marker must be on storage before it can become index.lock, so that a power loss never leaves a lock with an empty or partial marker. That flush is a few milliseconds on an idle disk and seconds on a loaded one, and it sat on every commit’s path. The batch number of the next landing is known when the last one ends (one more), and so is the index, so the file is made then. One file at most exists for the service, it is kept in this thread’s slot and not in a file other processes could take for their own, it is removed when the service ends or the next batch is not the one it was made for, and it names this process, so the next service removes what a crash left (remove_dead_staging). A commit that arrives while the flush is still running waits for it and does not start a second.
service_index_reclaim
The removal of a stale index lock, by a rename and a second look. What: The removal of a stale index lock by one reclaimer at a time: the reclaimer opens the lock it will judge, reads the marker from that open file, takes its place in the claim chain beside the lock, checks that the name still refers to that file, and only then unlinks the name. Why: A removal by name removes whatever the name holds by then. Between a look at the marker and the removal, the stale lock may be gone and a live lock in its place; that happens when a second reclaimer (another instance serving the same physical index, an alternate index shared by two worktrees, a service on another machine over a shared file system) removed the stale lock and placed its own. The earlier cure took the file aside by a rename and put it back by a hard link, which left the live lock off its name for a while, in which Git could take the name and strand it. Here no file is moved: the claim chain (service_index_claim.rs) lets one reclaimer of that file go on, and a reclaimer that opened it before it was removed finds the name no longer refers to it. The chain is used on every file system, because a reclaimer on the flock path and one on the claim path would not see each other. A live landing cannot place a lock while the name is occupied. What stays open is a person’s rm index.lock between the check and the unlink, because no system call unlinks a name only if it still names a given file (doc/planning/cli-git-one-reclaimer-per-index.md).
service_index_same
Whether a new index file holds the live index’s bytes. What: Whether a new index file holds the bytes of the live one. Why: The release of the index lock installs a copy only when it differs from the live index, so an unchanged index keeps its inode and its access list and costs no flush or rename. The module is split from service_index_hold.rs.
service_index_staging
The staging files of the index lock. What: The staging files of an index lock: their names, their creation with the marker written, and the removal of the ones a killed attempt left. Why: The marker is written to a file that is new and becomes the lock in one step, so the lock never exists without it. A staging name carries the process and a token no other attempt has, so no attempt opens a file another left, and a later attempt tells from the name alone whether the writer still runs. The module is split from service_index_placement.rs.
service_index_wait
The wait of a wrapped index writer for the commit service’s own hold on the index. What: The wait of a wrapped command that writes the index for the commit service’s own hold on the index: event-driven, with a notice that names what is waited for, and over as soon as the hold is released. Why: The service holds Git’s index.lock while it lands a commit and marks it as its own. A wrapped git add run by another process in the same worktree during that time must not fail, and must not be told the hold belongs to a program nobody can prove alive: the hold is the product’s own and ends by itself. A lock without the service’s mark is a foreign program’s and keeps the behavior of native Git. The wait blocks on an inotify watch set before the first look, so a release between the look and the wait is not missed. A service the mark proves to run is waited for with no bound.
service_index_watch
The inotify watch the wait for the index lock blocks on. What: The inotify watch on the directory of an index lock, and the reading of the events it delivers. Why: The service waits for a holder of index.lock without polling: the watch wakes it when the lock is removed or moved away, when the kernel reports an overflow that may have hidden that, or when the watch itself ended (the directory was unmounted or removed). Where no watch can be set (the platform has none, the watch limit is reached, or the file system gives none), the waits look at the lock again after POLL_PAUSE instead of failing or waiting blind. The module is split from service_index_lock.rs, which re-exports everything here under its old names.
service_land
The commit service’s serialized step. What: The service’s serialized step: land a batch of prepared commits on a branch, and finish the batches a killed service left open. Why: Everything that must happen one commit at a time happens here, in a fixed order, with one durable write: the objects of the whole batch are written by one fast-import, the intent is journaled, the branch moves by one compare-and-swap, the index entries of the named paths are updated, and the intent is marked done (doc/planning/cli-git-resident-service.md, “The serialized step, group commit, FIFO and backpressure”).
service_land_copy
What the commit service’s landing does once the branch has moved: index entries and conclusion state. What: The landing’s private copy of the live index: a directory this landing made for itself beside the live index, holding the copy and a marker that names the service that owns it. Why: Every name beside the live index can be another program’s (a client’s GIT_INDEX_FILE, a lock of another client), so a copy kept under a name there can be taken, shared, or run out of names. A directory with a random name is made exclusively, and everything the landing builds lives inside it: Git’s own lock for the copy, the in-process update’s temporary file, and the copy. It is made owner-only before the first byte goes in, it has the same file system as the live index so that one rename installs the copy, and it is removed when the value is dropped. The owner holds an exclusive flock on the directory for as long as the value lives, and the kernel drops it when the owner dies, so a directory a service that died left is the one nobody holds: no process number, boot or PID namespace is asked, which a recycled number, a container or a service killed before it wrote a marker would answer wrongly.
service_land_finish
What: What follows the branch move of a landing and of a restart: the conclusion state and the index update, and the decision whether a batch a killed or failed landing left open may be replayed. Why: A replay runs after the lock the landing held was given up or lost, so another program may have staged into the index since. A replay is made only over the very index file the landing saw under its lock (service_land_start.rs), under the lock the restart takes, and the head is checked again under that lock; every other case leaves the index as its writers left it, says so in the service’s log, and finishes what does not touch the index. The live landing and the restart share the one routine that finishes a batch, so an alternate index and the conclusion state are settled the same way by both (doc/planning/cli-git-main-commit-within-native-plus-five.md, “A replay only over the index the landing saw”).
service_land_follow
What: What the service’s landing does once the branch has moved: the worktree’s index entries of the commit’s paths and the conclusion state a merge, cherry-pick or revert leaves behind. Why: A commit Git built in a scratch repository carries no list of changes, and a conclusion’s state files belong to the commit that concludes it. Both steps are idempotent, so the same code finishes a batch a killed service left open. The index entries come from the repository itself: the paths that differ between the branch before and the commit, as bytes, handed to reset on its standard input, so a name that is not UTF-8, a long list and a gitlink need no special case (doc/planning/cli-git-resident-service.md, “Landing every command line”).
service_land_start
What: The witness of the live index file as the landing found it under the index lock, recorded in the journal, and the comparison a replay makes with it. Why: An index update that never installed is replayed by a restart after the lock was given up, and another session may have staged into the index since. What the index holds at a path cannot tell a path nobody staged from a path staged back to the same entry (stage another version, then the old one again): both read the same. The file itself can tell. Every program that changes an index writes a new file and renames it over the old one, so a file that is still the one the landing saw (same inode, size, change time, modification time and checksum) has been written by nobody since, and a replay over it discards nothing. Any other file might hold staging, so the replay is not made over it (doc/planning/cli-git-main-commit-within-native-plus-five.md, “A replay only over the index the landing saw”).
service_message
The message and identities of a service commit, made as native git commit makes them. What: The message and the identities of a commit the service lands, made from the command line the way native git commit makes them when no editor opens. Why: Everything here is text arithmetic that Git itself defines (clean-up, sign-off, trailers, the subject of a fixup, the message and authorship of a reused commit), so the wrapper embeds it instead of starting git commit; each rule is compared field by field with the native commit in binary_service_options_tests.rs. Whatever cannot be made without guessing returns nothing and native git commit handles the line.
service_messages
What the user is told when the commit service cannot land a commit. What: Everything the wrapper tells the user when it cannot get a commit landed by the resident service, and the notices it prints while it waits. Why: A failure the system can resolve is resolved without the user; the rest ends the command with plain words, the affected input named, every remedy given, and no implementation term (doc/planning/cli-git-resident-service.md, “Failures the client can meet”). The texts live here as constants so a test can check each against a list of terms that must never reach a user, and so the text a client prints cannot drift from the text the tests read.
service_native
The commits real Git builds for the service: an editor, a signature, and what the service does not embed. What: The commits real Git builds for the commit service: an editor, a signature, and every command line the service does not build itself. Why: Git owns the editor, the signer and the message semantics of whatever the service cannot embed, so this module points real git commit at a thin scratch repository (its HEAD and branch at the base, the policy-settled private index, the real configuration included, every hook off) whose new objects go straight into the real object store. Nothing is locked and nothing is registered: the scratch repository sits inside the commit’s own scratch directory, is removed with it, and the commit it makes is only an object until the service moves the branch to it by compare-and-swap (doc/planning/cli-git-resident-service.md, “Commits Git builds”).
service_prepare
The preparation of a commit that the service lands, for every command line. What: The preparation of a commit that goes through the resident service: the private index, the selection UI, the policies, the settled changes, and the facts the landing needs, for every command line. Why: The service lands what is prepared here, so the preparation covers every shape of commit: a branch, a detached head or a branch that does not exist yet, an ordinary commit or the conclusion of a merge, a cherry-pick or a revert, a selection by path, by --include, by --patch/--interactive or by a pathspec file, and a policy that rewrote a file. Whatever Git alone can answer (an unmerged index, nothing to commit) is marked for Git to answer in the scratch repository, so its words and its exit status are the person’s. Nothing here locks anything, and nothing is registered (doc/planning/cli-git-resident-service.md, “Landing every command line”).
service_pruned
How a commit headed for the service notices that its prepared content was removed before it landed. What: How a commit headed for the service notices that the content it prepared was removed from the repository before it landed: the policy read that fails on a missing object, the check of the request’s objects after the service could not land it, and the numbered phase markers a test uses to remove content at a chosen instant. Why: A commit’s blobs, trees and commit object are unreferenced until the branch moves, and git gc --prune=now deletes every unreferenced object at once. The Git manual for git gc (the installed 2.56.0 manual and https://git-scm.com/docs/git-gc, section NOTES, checked 2026-11-01) says: “when git gc runs concurrently with another process, there is a risk of it deleting an object that the other process is using but hasn’t created a reference to. This may just cause the other process to fail or may corrupt the repository if the other process later adds a reference to the deleted object”, and for the option itself: “–prune=now prunes loose objects regardless of their age and increases the risk of corruption if another process is writing to the repository concurrently”. Git’s own mitigation is the two-week grace of the default --prune date, which --prune=now removes. This commit path therefore says plainly what happened and what to do (ClientFailure::ContentPruned), instead of showing a policy event for a machine or a failure of the service. It does not prepare the commit again: the bytes the command captured are what is gone, and reading the worktree again would commit whatever it holds by then.
service_replay
The retry of a commit the service sent back: the captured change merged onto the branch, never prepared again from the worktree. What: The retry of a commit the service sent back because a path it names changed on the branch since its base: the change the first preparation captured is merged onto the branch as it is now, and the worktree is not read again. Why: A commit lands the bytes that were there when the person ran the command (doc/decision/cli-git-concurrent-commits.md, “Serial landing”; SPEC.md: “Cli-git never re-prepares a commit from current worktree bytes”). Preparing again from the worktree landed bytes written after the command, and bytes another command meant. The merge base is the preparation base, and a path the other commits changed that the captured change already contains is kept as captured (the same subsumption rule the earlier landing path applies, replay_subsumption.rs). The first merge is one Git run; the subsumption runs only for the paths that conflicted, so a retry that merges cleanly costs three runs here: write-tree for the captured tree, merge-tree, and read-tree of the merged tree into the private index.
service_retry
The repositories the service looks at again when a claim another instance holds may have run out. What: The repositories the service must look at again, and when: those with a claim that another instance holds and that may run out its lease while this service sits idle. Why: A restarted service that finds the claims of the instance it replaces cannot take them before their lease is over, and nothing wakes it when the lease is: the next commit might be hours away, and the work would sit claimed by a holder that died. The work loop asks this schedule how long to wait for a wake before it looks again.
service_round
The drain of several repositories of one round, side by side and without a lock. What: The drain of several repositories in one round of the service’s after-commit work, side by side. Why: Repositories share nothing: each has its own work directory, its own claims and its own pushes, so one repository’s slow push or review never needs to hold up another’s. The round’s thread hands each repository to a worker and takes the answers back in the order the repositories were named (parallel_runner.rs), so the retry list is the one a drain of one after another gives. No lock is taken (service_lock_inventory_tests.rs): the handlers are shared read-only, every claim is made by an atomic rename as before, and the directories of one repository (a main checkout and its linked worktrees) share a lane and are drained one after another there, because they share a work directory and its upkeep.
service_route
Which way a commit goes: through the service, set up first, or the earlier path. What: How a commit reaches the resident service: already listening, or set up first by the wrapper. Why: There is no switch and no install state for the person to manage (doc/planning/cli-git-resident-service.md, “Provisioning”). The route follows the machine: a user session bus and a service program next to the wrapper mean the wrapper can set the service up itself, and keeps it set up (the socket is the manager’s and outlives every upgrade, so its presence never says the installed units name this release’s program); a socket without them is used as it is; anything else has no route, and the commit stops with the plain message of its platform, because the service is the only writer of a commit. The decision reads the file system only and starts no process.
service_work
The service’s consumer of after-commit push and upkeep work. What: The service’s consumer of after-commit work: pending push and maintenance work items of one repository are claimed, coalesced, run, settled, and a push that failed leaves a record that the person’s next wrapper command shows. Why: A commit must not wait for the network or for upkeep, so the wrapper leaves a record and the resident service does the work on its own thread (doc/planning/cli-git-resident-service.md, “After-commit work”). The service is the only pusher of the repositories it serves, so no lock is needed: several pending pushes of one branch become one push, and a service that died mid-push is noticed by the lease of its claims running out, never by a process id: the holder renews the lease while it works, so a successor that starts beside a holder that is still running leaves its claims alone, and one that starts after the holder died takes them back as soon as the lease is over. Other kinds of work (the standards review) are never claimed here.
work_item
The durable work-item record for asynchronous work (review, push, maintenance) left for a resident consumer. What: The durable work-item record: a small file in the Git directory that says “this landed object needs this asynchronous work”, written by the wrapper and drained by a separate resident consumer. Why: A wrapper process exits when its command ends, and it may start no program, so work that must not delay a landing (the standards review, later auto-push and maintenance) is left as a record instead. The record is generic: a kind, the landed object and an id derived from both, so a retry cannot duplicate it. The design, its failure cases and the consumer contract are in doc/planning/cli-git-standards-review-port.md. Nothing calls this yet.
work_item_recovery
What: The recovery half of the work-item record: the claims whose lease ran out go back to pending (or to failed), and a killed recovery’s leftovers are removed. Why: A consumer killed at any instruction is noticed by its lease, never by a process id; the code is apart from work_item.rs so each file stays within the size limit, and work_item.rs re-exports what callers use.