Skip to main content

Module staged_only

Module staged_only 

Source
Expand description

Make the checks see what is being committed.

staged_files() asks the index for the PATH LIST, which is right, and then hands those paths to tools that open them from the WORKING TREE. Eleven of the fifteen pre-commit checks do this. So git add -p half a file, commit, and prettier reads the whole working-tree file: it fails on lines you did not stage, or passes on lines you did.

pre-commit fixes this for everyone by stashing the unstaged changes for the duration of the run, and their wording names both directions:

Running hooks on unstaged changes can lead to both false-positives and false-negatives during committing.

§This is the most dangerous code in the repository

A stash taken and not restored loses uncommitted work. That is worse than either failure that overwrote tracked files, because there is nothing on disk to recover from. Hence, in order of how likely each is to bite:

  1. Nothing to stash → nothing happens. The common case never touches the tree.
  2. Restore on a SIGNAL. Drop runs on unwind and on early return; it does NOT run when Ctrl-C kills the process, and interrupting a slow pre-commit is the most probable route to an orphaned stash, not the least.
  3. Restore in Drop for panics and early returns.
  4. Never mid-operation. A merge or rebase in progress means the tree is already holding somebody else’s work — GitState (PR 2) answers this.
  5. Restore failure is loud and fatal, and prints the store’s path, so the work is findable on disk rather than silently gone. (Not git stash list: nothing here is a stash ref — see the impl comment below for why byte-exact copies beat both stash --keep-index and a patch.)
  6. amont restore for when even the handler was interrupted.

The store describes itself in an index file, and every repo-controlled path lives under files/. Both because the store used to encode its metadata in the payload FILENAMES, which a repository is allowed to collide with — and did, deleting a tracked file and planting a symlink outside the worktree. See [Held].

Structs§

StagedOnly
Unstaged changes, set aside for the duration of a stage.

Constants§

STORE
Where the unstaged changes are parked. Inside $GIT_DIR so they are never committed, never seen by a check, and findable by hand.

Functions§

install_signal_handler
Restore before dying on a signal.
restore_command
Put back files this tool parked, from a later invocation.