Skip to main content

Module worktree_copying

Module worktree_copying 

Source
Expand description

Copying the ignored state of a linked worktree into a new one, with staging, journal and recovery. What: Copying the ignored state of a linked worktree into a new one, with staging, journal and recovery. Why: The copy is a transaction of its own with many small steps.

In TS you’d write (pseudocode):

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

Modules§

worktree_copy
The linked-worktree ignored-state copy around one forwarded Git invocation: the integrator’s entry point. What: The linked-worktree ignored-state copy around one forwarded Git invocation: the public entry point the integrator calls, the settlement and summary it writes, and the exit status it returns. Why: A worktree that Git creates (or a bare repository’s) needs its ignored files from the source worktree. No lock stands around the command: the destination comes from the command line, the copy is a transaction of its own (a journal and a stage claim that name their owner process), and a copy a dead process left is recovered first by the next command. Concurrent adds in one repository never wait for one another (the owner’s decision of 2026-11-03).
worktree_copy_compare
Exact comparison of manifest entries against the filesystem, and the source stability check after staging. What: Exact comparison of one manifest entry against the filesystem: its kind, its retained mode, its symbolic-link target text or its regular-file bytes. Also the final check that the source still matches the stage after staging. Why: A destination must receive exactly what was staged from the source, and a source that changed during the transfer must block the destination.
worktree_copy_error
The one failure type of the linked-worktree ignored-state copy and its diagnostics. What: The one failure type of the linked-worktree ignored-state copy, with the complete user-facing diagnostic in its message. Why: Every copy step fails with a message that names the path it could not handle and, when there is one, the operating system’s cause. The incumbent renders the cause after the message with a fixed separator, so both wrappers print the same words.
worktree_copy_forward
Which forwarded invocations the copy applies to, and the child run that performs it. What: Running a forwarded Git command through the linked-worktree ignored-state copy: which invocations the copy applies to, and the child-process run that performs it. Why: A command that creates a worktree must copy the ignored state once real Git returns, and a command run from a linked worktree must first recover a copy a dead process left; replacing the process with Git would drop both duties, so these invocations run Git as a child. No lock is held: concurrent commands never wait for one another. The main checkout is a source only for the configured rules file, so it takes this path only when the command creates a worktree and the configuration names that file.
worktree_copy_install
Installation of a validated stage into a new worktree, with preflight, batches and rollback on failure. What: Installation of one validated stage into a newly registered worktree: preflight of every existing destination entry, batched creation with its durable records, mode application and rollback of this installation’s own paths when it fails. Why: A destination that already holds an identical entry is accepted, and a differing entry is never overwritten, so the copy cannot destroy user state. Recording each batch before and after it runs bounds the work an interrupted run leaves unrecorded.
worktree_copy_install_entry
The exclusive creation of one destination entry from the stage, and the identity captured after it. What: The exclusive creation of one destination entry from the private stage, the identity captured right after it exists, and the creation of the unselected parent directories an entry needs. Why: A regular file is installed as a hard link to its staged copy, so it appears with its final bytes and mode in one step; the identity captured after creation is the only proof later rollback accepts.
worktree_copy_install_log
The append-only install log of one stage: per-batch intents and creations, with resumption. What: The append-only install log inside one transaction’s private stage: one synced JSON line per batch of intents and one per batch of proven creations. Why: The journal header changes only with the phase, so the per-batch records live here; bytes written then grow with the entry count instead of with the square of it.
worktree_copy_journal
The durable journal of one copy: exact encoding, strict validation, private storage and removal. What: The durable journal of one destination’s linked-worktree copy: its exact JSON encoding, strict validation of every field recovery will act on, private storage under <common>/cli-git-worktree-copy/v1, and removal of a finished transaction’s stage and journal. Why: A crash can happen after any step, so the journal must say which phase the copy reached and which paths it may have touched, and recovery must never act on a journal it cannot prove is its own.
worktree_copy_manifest
The deterministic parent-first manifest of a copy, and the mode application to a staged copy. What: The deterministic, parent-first list of entries a copy transfers, read without following symbolic links, and the application of the retained permission bits to a staged copy. Why: The stage and the source are compared entry by entry, so both sides must enumerate in the same order and classify the same way. Sockets, FIFOs and device nodes stop the walk before any of them is opened.
worktree_copy_owner
The process that owns one item of a copy transaction, written into the item’s name, and the proof that it still runs. What: The process that owns one item of a copy transaction (a journal, a stage claim, a temporary file), written into the item’s own name or text, and the proof of whether that process still runs. Why: Concurrent adds in one repository must never wait for one another, so no lock stands between them. An item has exactly one owner, and any other command may touch an item only when its owner is proven dead: the live copy of an add is never recovered or reaped, a dead one is. The owner is part of the item’s name, so taking over a dead owner’s journal is one atomic rename (a single winner, no lock file, no stale lock to retire).
worktree_copy_prune
What a copy from a main checkout leaves out: caches, optionally run records, and other checkouts. What: What a copy from a main checkout leaves out of the ignored state it hands over: caches, optionally the records of earlier runs, and every directory that is another checkout. Why: A worktree added from the main checkout should work at once, so builds and installed dependencies are copied, but a cache is rebuilt by its tool, a log of an earlier run is no input, and another checkout’s files would make the new worktree a second claimant of that checkout’s administrative state. The rule is a handful of directory names rather than a list of paths, so a reader can predict it (doc/planning/cli-git-main-worktree-ignored-copy.md measures the set it leaves out).
worktree_copy_recovery
Recovery of interrupted copies: registration checks, discards with notices, resumption, and the pending check. What: Recovery of interrupted linked-worktree copies: every pending journal is resumed, completed, or discarded with a notice; malformed state fails closed and stays; the pending check that forwarded commands run first. Why: A copy interrupted by a crash must not leave a worktree half-filled forever, but recovery may only act on journals whose destination is still a registration of this repository and whose stage is still private.
worktree_copy_registry
Which linked worktrees a worktree-creating Git command registered, before and after it ran. What: The linked worktree a git worktree add registered at the destination its command line names: whether that destination was a registered worktree before real Git ran, and whether it is one registered by this command after Git returned, with the canonical root of every registered worktree. Why: The destination is read from the command line and its registration is found by following the pointer in its .git file, so a concurrent add in the same repository can neither be mistaken for this one’s worktree nor make this one wait (the earlier comparison of the whole set of registrations needed a lock to keep other adds out of its window). A worktree that Git registered before failing still receives the ignored files, so the check runs after Git returns whatever its status was. The main worktree is observed only through observe_copy_source, which the caller reaches only for a command that creates a worktree, so its other invocations cost no filesystem reads.
worktree_copy_rollback
Removal of the paths a failed installation created, only where their identity and content still prove them cli-git’s own. What: Removal of the paths one failed installation created, child first, and only where the filesystem still proves they are cli-git’s own. Why: A failed installation must not leave a partial worktree, but it also must never delete a path the user or another process put there after cli-git created it.
worktree_copy_selection
The ignored source paths a linked-worktree copy selects, and the path validation every selection passes. What: Which source paths the linked-worktree copy selects: the ignored roots Git reports under the standard exclusion stack, the ignored special entries (sockets, FIFOs, devices) Git’s listing omits, and the validation every repository path passes before it touches the filesystem. Why: Git decides what is ignored; the copy only adds the entries Git’s index-oriented listing cannot report, and it never trusts a path that could leave the worktree.
worktree_copy_stage
The private, validated stage of one source’s ignored state beside a destination worktree. What: The private, validated copy of one source’s ignored state, staged in a mode-0700 directory beside a destination worktree. Why: The stage sits on the destination’s filesystem, so a file clone stays local and the install is a rename or a link. The source is copied entry by entry and compared again at the end, so a source that changed during the copy never reaches the destination.
worktree_copy_stage_claim
The durable claim on a stage container’s name, and the removal of stages an interrupted copy left behind. What: The durable claim on a stage container’s name, written before the container exists, and the cleanup of containers whose copy was interrupted before its journal was written. Why: Staging a worktree’s ignored state takes minutes and gigabytes, and the journal is written only after it. A process killed in between (a signal, the out-of-memory killer, a power loss) leaves a stage nothing names. The claim names it first, so the next recovery pass, which skips every claim whose owner still runs, removes it with a notice instead of leaving it to fill the disk.
worktree_copy_transaction
One journaled installation to an end, resumption from the log, and synchronization of a created worktree. What: One destination’s journaled installation to an end, and the synchronization of every created worktree. The journal records the phase, the install log records each batch’s claims and creations, and a finished or failed installation always removes its journal and stage. Why: A failed installation must not stay pending, because recovery would replay the same failure before every later command; an interrupted one must resume from exactly what it recorded.