Skip to content

The commit-msg hook blocks commits in a shallow clone and on multi-block messages #352

Description

@MongLong0214

Two ways the hook exits non-zero for a reason that is not "the record is invalid". Found by a production audit of v0.5.1.

1. Shallow clone → dangling-ref

src/commands/validate.ts:550-699 gates on notes === 'unfetched' (:588, :620) and has no shallow gate. grep -c shallow src/commands/validate.ts0, though src/core/git.ts:144 hasShallowHistory exists and is used by query.ts:834, doctor.ts:675, before-change.ts:81.

Same message, same upstream:

--depth 1 clone : shape ok · references failed
                  dangling-ref Supersedes — got "r-old001"     exit 1  -> commit blocked
full clone      : shape ok · references ok                     exit 0

The record is not invalid; the history is truncated. actions/checkout defaults to fetch-depth: 1.

The team already guards the mirror-image hazard: action/lint/lint.mjs:128-139 refuses on a shallow checkout, commented "Linting what a shallow clone happens to contain would report a green check." The local hook has the red-check version and no guard.

2. Multi-block message → dangling-ref on any block but the first

src/commands/validate.ts:509:

const identity = `${row.sha}\0${row.source}`;

No block. The index's row identity is (commit_sha, source, block, seq) (src/core/index-db.ts:195), and src/core/query.ts:469 keys on all four specifically to fix this class (bug-issue-92). Flattened, the group carries several Record-Id trailers and src/core/stale.ts:90 returns only the first, so only block 0 reaches the declared set.

Follows: r-aaa111  (block 0) -> exit 0
Follows: r-bbb222  (block 1) -> exit 1  dangling-ref  -> commit blocked

context reports both records. Multi-block messages are produced by this project's own squash inheritance (src/hooks/prepare-commit-msg.ts:55-68) and by GitHub's squash button.

Why these matter more than an ordinary bug

A hook that blocks a commit it cannot evaluate is the failure mode that gets a tool uninstalled — or --no-verify'd permanently, which is worse because the guard is then off for the commits that need it.

Both untested.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions