# Selected-path Git maintenance The optional `git` namespace of `tools/devkit/devkit.py` is a deliberately narrow maintenance workflow. It is not a replacement for normal Git, the release executor, required human review, or Gitea's canonical issue state. From the Meta repository, preview and then save a plan for explicit files: ```sh python3 tools/devkit/devkit.py git plan --repo core --path webui/src/example.ts --message "Fix the reviewed example" python3 tools/devkit/devkit.py git plan --repo core --path webui/src/example.ts --message "Fix the reviewed example" --apply ``` Use the saved `git-…` plan ID for the remaining commands. Each mutation needs its own `--apply`; an unqualified command only previews the operation: ```sh python3 tools/devkit/devkit.py git commit git-PLAN_ID python3 tools/devkit/devkit.py git commit git-PLAN_ID --apply python3 tools/devkit/devkit.py git push git-PLAN_ID python3 tools/devkit/devkit.py git push git-PLAN_ID --apply python3 tools/devkit/devkit.py git status git-PLAN_ID ``` The immutable local plan binds the registered repository, HEAD, branch, origin fetch/push URL hashes, Git configuration, complete index identity, explicit selected file paths, working-tree hashes, expected Git blobs, and commit message. Raw remote URLs and file contents are not stored. A changed input blocks the operation; inspect it and create another plan instead of weakening the check. Receipts are private local records with integrity checks, not signed approval or a security attestation. Commit captures each selected file once, verifies the captured bytes and Git blob against the plan, and builds an isolated index/tree from the frozen HEAD plus only those blobs. Git's normal identity rules create the commit object; an atomic branch compare-and-swap publishes it only if the planned parent is still current. Active hooks/signing remain refused rather than bypassed. An editor racing with this operation cannot substitute newer working-tree bytes: those edits remain uncommitted, and the helper never overwrites files. The real index is protected by Git's standard index lock. Only selected entries are updated from a prepared private copy; unrelated staging and index flags are preserved. If the index changes independently, its new data is not overwritten and the receipt requires reconciliation. The resulting parent, message, changed paths, blobs/modes and unrelated index entries are verified. Git refs and index files are separately atomic, not one filesystem transaction. Independent writers that ignore the standard index lock can still change refs during publication. The helper rechecks the exact recorded candidate before index recovery and before recording success; it refuses an uncertain result instead of adopting a newer HEAD or claiming that competing work was its own. Directories, noncanonical paths, implicit globs, staging-all, amend, force-push and extra-tag publication are not supported. A selected file with different staged and working-tree changes is refused; decide explicitly which version to commit using normal Git first. Push requires the recorded commit to remain current, an unchanged origin and one standard-transport push destination. It requests a normal, non-forced push of that commit to the recorded branch and checks the remote branch afterward. The push preview does not contact a remote. A normal push may run the remote's usual CI or server-side hooks; this is an external effect of the separately authorized push, not of planning or committing. Local active hooks (including index-change hooks), filter/encoding attributes, signing, external fsmonitor/SSH configuration, Git environment overrides, in-progress merge/rebase/cherry-pick operations, submodules, symlinks and assume-unchanged/skip-worktree entries, split indexes and replacement/graft history are deliberately unsupported. The helper refuses these cases instead of disabling hooks, signatures or filters. An unused globally installed filter definition alone does not block maintenance; active attributes are checked across tracked files as well as selected files. Custom remote receive-pack/upload-pack/helper commands, recursive submodule pushes and partial-clone lazy fetch are also refused. Of inherited `GIT_*` variables, only `GIT_OPTIONAL_LOCKS`, `GIT_TERMINAL_PROMPT` and `GIT_PAGER` are allowed (every command explicitly passes `--no-pager`, so the pager is inert); namespace, identity, alternate-index/object-directory and unknown overrides are not silently removed. Git subprocesses have bounded input/output and deadlines; cancellation terminates their owned process group, including transport helpers. Network failures can still leave a remote effect uncertain, which is why receipts require explicit reconciliation rather than blind retry. An interruption or uncertain failure is recorded before any retry. Use `git reconcile git-PLAN_ID` to preview, then add `--apply` to verify an already-existing result. Reconciliation never makes a commit or push. It may finish the selected real-index update after an interrupted commit publication, but only when the original index fingerprint still matches; independent staged work is preserved and requires normal Git resolution. For an uncertain push it may read the frozen remote, but only with `--apply`. If no planned commit is current, the helper reports that state and requires a fresh plan after inspection. A forcibly killed process may leave its private scratch index or an owned Git index lock; the helper never guesses that an existing lock is safe to delete. Blob/commit preparation can leave unreferenced Git objects for ordinary Git garbage collection. It never automatically resets, restores, deletes, or rolls back user work. The maintenance tests use disposable local repositories and local bare remotes. They never commit or push the user's workspace repositories.