Changed mode
alint check --changed layers a diff filter on top of the walk so a per-file rule sees only the files you touched, which is what a pre-commit hook or a PR check wants. Most cross-file rules, and the existence rules, deliberately opt out and keep evaluating the whole tree, because an invariant they enforce can be broken by a file you changed even when its partner did not.
The two diff modes
Section titled “The two diff modes”--changed picks its diff from git in one of two shapes:
| Invocation | Diff source | Fits |
|---|---|---|
alint check --changed | working tree: modified plus untracked, --exclude-standard | pre-commit, local dev |
alint check --changed --base=main | main...HEAD (three-dot, merge-base) | PR checks |
The three-dot <base>...HEAD form diffs against the merge-base of <base> and HEAD, which is exactly what a GitHub PR calls “your changes.” --base=<ref> implies --changed, so the ref is the verb’s argument; you never pass both --changed and a bare --base awkwardly. The same flags work on alint fix --changed.
Which rules stay whole-tree
Section titled “Which rules stay whole-tree”The filter narrows the file set for per-file rules only. Two families opt out, on purpose:
- Whole-tree rules always evaluate against the whole tree, because their verdict depends on files outside your diff: the relational rules (
pair,for_each_dir,for_each_file,every_matching_has,unique_by,dir_contains,dir_only_contains), the manifest and graph rules (cross_file,file_graph,registry_paths_resolve,pair_hash), and the single-shot rules (generated_file_fresh,command_idempotent). Apairrule that requires everyapi.hto have anapi.cmust still fire when you deleteapi.c, even though the survivingapi.his not itself in your diff. - Existence rules also consult the whole tree, but the two file-existence rules (
file_exists,file_absent) are skipped when theirpaths:scope does not intersect the diff, so a missingLICENSEfails only the PRs that touch aLICENSE-shaped path. The two directory-existence rules (dir_exists,dir_absent) always evaluate, since a directory scope never intersects a file-path diff. - Diff-oriented rules are the mirror image: a few cross-file rules exist because of the diff.
pair_changed_togetherasks whether a file’s partner changed alongside it, andchangeset_requires_pathgates on what a commit range touched, so they read the changed set by design;markdown_paths_resolveis likewise a per-file rule and follows the diff filter like any other.
Edge cases
Section titled “Edge cases”- Empty diff (nothing modified, nothing untracked): the run short-circuits to an empty report in milliseconds, so a no-op pre-commit is nearly free.
- Outside a git repo (or
gitmissing fromPATH):--changedhard-errors rather than silently falling back to a full check, because a silent full run would betray the intent the flag expressed. - Deleted files appear in the diff. A
LICENSEyou deleted is in the changed set, the walker no longer sees it on disk, and an existence rule forLICENSEevaluates the whole tree (which now lacks it) and fires.
--changed pairs naturally with git_tracked_only:: the changed set is a working-tree concept and the tracked set is an index concept, so a rule with both fires only on tracked entries that are part of this diff.
In practice
Section titled “In practice”A PR check that lints only the files the branch touched, against the merge-base:
alint check --changed --base=origin/mainIf the branch added a trailing-whitespace line to src/parser.rs and deleted api.c (leaving api.h orphaned), one report carries both a per-file finding and a whole-tree one:
warning no-trailing-whitespace trailing whitespaceerror header-source-pair api.h has no matching api.cThe no-trailing-whitespace finding came through the diff filter; the pair finding came from the whole-tree pass, even though api.h was never in the diff.
Going deeper
Section titled “Going deeper”- The walker and git is the whole-tree index this filter sits on top of.
- Scoping covers
changed_since:, the per-rule scope_filter counterpart to the run-wide--changed. - Configuration documents the rule kinds and their cross-file versus per-file classification.