Found by a production audit of v0.5.1 and reproduced.
Reproduced
$ commitlore init
hooks after init: commit-msg post-commit prepare-commit-msg
$ commitlore hooks uninstall
removed commit-msg hook: …/.git/hooks/commit-msg
hooks remaining: post-commit prepare-commit-msg
init installs three (src/commands/init.ts:101-104). hooks uninstall removes one — HOOK_NAME = 'commit-msg' (src/hooks/commit-msg.ts:24), and the command's own description says so (src/commands/hooks.ts:374).
Why the leftovers matter
prepareCommitMsgStub is derived from the commit-msg stub by string replacement (src/hooks/prepare-commit-msg.ts:20-23), so it inherits the fail-closed ending — exit 1 when it cannot find the CLI (src/hooks/commit-msg.ts:188-190).
So after commitlore uninstall removes the pinned checkout, the two remaining hooks cannot resolve a CLI, and:
$ git commit -m "…"
commitlore: cannot find the CLI this hook was installed with.
$ git log --oneline
30ae54e seed ← the commit never landed
Every commit in every repository where init ran is blocked, and the remedy the message names requires the binary that was just deleted.
Two separate defects
hooks uninstall is incomplete. It should remove all three, or grow --all, or say plainly which one it removes. The README wording was corrected to name the real scope, but the command is still the wrong shape for what init does.
prepare-commit-msg and post-commit should fail open. They are not validation gates. commit-msg is the one that decides whether a record is valid, and it is the only one with a reason to refuse. The other two inherit a refusal that belongs to a different job.
(2) is the one that turns an incomplete uninstall into a repository that cannot accept commits, and it is worth fixing on its own regardless of (1).
Related
The recovery path stated in the 0.5.0 and 0.5.1 notes — re-run commitlore hooks install — also only reinstalls commit-msg.
Found by a production audit of v0.5.1 and reproduced.
Reproduced
initinstalls three (src/commands/init.ts:101-104).hooks uninstallremoves one —HOOK_NAME = 'commit-msg'(src/hooks/commit-msg.ts:24), and the command's own description says so (src/commands/hooks.ts:374).Why the leftovers matter
prepareCommitMsgStubis derived from the commit-msg stub by string replacement (src/hooks/prepare-commit-msg.ts:20-23), so it inherits the fail-closed ending —exit 1when it cannot find the CLI (src/hooks/commit-msg.ts:188-190).So after
commitlore uninstallremoves the pinned checkout, the two remaining hooks cannot resolve a CLI, and:Every commit in every repository where
initran is blocked, and the remedy the message names requires the binary that was just deleted.Two separate defects
hooks uninstallis incomplete. It should remove all three, or grow--all, or say plainly which one it removes. The README wording was corrected to name the real scope, but the command is still the wrong shape for whatinitdoes.prepare-commit-msgandpost-commitshould fail open. They are not validation gates.commit-msgis the one that decides whether a record is valid, and it is the only one with a reason to refuse. The other two inherit a refusal that belongs to a different job.(2) is the one that turns an incomplete uninstall into a repository that cannot accept commits, and it is worth fixing on its own regardless of (1).
Related
The recovery path stated in the 0.5.0 and 0.5.1 notes — re-run
commitlore hooks install— also only reinstallscommit-msg.