Skip to content

feat: report only what a commit or branch changes with --staged and --base - #35

Draft
fcbwilliams wants to merge 2 commits into
mainfrom
feat/changed-files-runs
Draft

fcbwilliams wants to merge 2 commits into
mainfrom
feat/changed-files-runs

Conversation

@fcbwilliams

Copy link
Copy Markdown
Member

What

Two exclusive options on check narrow what is reported to what a change touches:

  • --staged reports only violations about files staged in the index, for a pre-commit hook.
  • --base <rev> reports only violations about files changed by the commits since the merge base of <rev> and HEAD, for a pre-push hook or a pull request.

runChecks takes the same narrowing as files and echoes it in the result.

Every check still reads the whole workspace, so cross-file checks keep their full view; only what is reported is narrowed:

  • A violation is reported when the file it names changed, or, if it names a directory (single-storybook's .storybook), when a file under that directory changed.
  • A violation about the repository's settings is always reported.
  • A violation naming a path that does not exist (a missing config, a pattern) cannot be tied to a change, so it is always reported rather than hidden.

The changed files come from git diff --name-only --no-renames --relative -z. A rename counts as both paths, a deletion counts, and paths are relative to --cwd. An empty --base, or one starting with -, is refused. When git fails, the error says what git said and why the run needed it.

The README section Checking only what changed covers the hook setup and the limits. It recommends running --staged directly from .husky/pre-commit, because lint-staged skips commits that only delete files. It also notes that a scoped run cannot see a change that breaks a check at a file it did not touch, so CI should still run the full check.

Why

A repository adopting a check today has to fix every existing violation before it can commit anything, because the tool judges the whole tree. Scoped runs let a hook block only the violations a change introduces, and the full run stays in CI. This came up in an assessment of using this tool for deterministic pre-commit enforcement, where the lack of a staged or changed-files mode was the main gap.

Tests

  • CLI (cli-command.integration.test.ts, git fixtures): staged files only, a staged deletion, --base reporting only the branch's own changes (merge-base semantics, including a base branch that moved on), a --cwd subdirectory with JSON files, refusal of both flags together, an empty base, an option-like base and an unknown revision.
  • runChecks: narrowing, directory violations, violations at missing paths and settings violations.

pnpm lint:check, pnpm typecheck and pnpm test pass locally.

🤖 Generated with Claude Code

fcbwilliams and others added 2 commits October 28, 2026 16:36
…-base

A pre-commit or pre-push hook should judge the change being made, not
every violation already in the tree, or a repository adopting a check
cannot commit until it has fixed everything at once. `check --staged`
reports only violations about files staged in the index, and
`check --base <rev>` only those about files the commits since the merge
base of <rev> and HEAD change. runChecks takes the same narrowing as
`files`. Every check still reads the whole workspace, so cross-file
checks keep their full view; violations about the repository's settings
name no file and are always reported. The README gives a lint-staged
recipe and the limits of a scoped run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…an empty base

A violation that names a directory (single-storybook's .storybook) is
reported when a file under it changed, and one naming a path that does
not exist (a missing config, a pattern) is always reported, rather than
hidden from every scoped run. An empty --base, which compared HEAD with
itself and passed, is refused. A failed git diff now says what git said
and why the run needed it, and git may print up to 64 MiB. The README
runs --staged straight from the pre-commit hook, since lint-staged skips
commits that only delete files, and says what --base compares.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant