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:
- Nothing to stash → nothing happens. The common case never touches the tree.
- Restore on a SIGNAL.
Dropruns 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. - Restore in
Dropfor panics and early returns. - Never mid-operation. A merge or rebase in progress means the tree is
already holding somebody else’s work —
GitState(PR 2) answers this. - 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 theimplcomment below for why byte-exact copies beat bothstash --keep-indexand a patch.) amont restorefor 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§
- Staged
Only - Unstaged changes, set aside for the duration of a stage.
Constants§
- STORE
- Where the unstaged changes are parked. Inside
$GIT_DIRso 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.