Description
Problem
On a large suite, the fastest feedback loop is "run only what my branch touched", and bashunit cannot express it. Today the options are --rerun-failed (needs a previous failing run) or a hand-rolled git diff | xargs ./bashunit, which breaks on renames, deletions and quoting.
src/helper/git.sh exists but only holds get_latest_tag, so there is no git plumbing to build on yet.
Proposal
--changed [<ref>] Run only test files changed since <ref> (default: origin/HEAD, then HEAD)
Selection set:
- Test files added or modified in
git diff --name-only --diff-filter=d <ref>...HEAD, plus uncommitted changes in the working tree and index. - Filtered to files that match the test-file pattern and live under the given path argument.
Deleted test files are dropped (--diff-filter=d). Behaviour when not inside a git work tree, or when <ref> does not resolve: exit non-zero with a clear message rather than silently running everything (#871 class of bug).
Explicitly out of scope for this issue: mapping source changes to the tests that cover them. That needs a @covers-style annotation and should be its own issue if wanted.
Where to change
src/helper/git.sh— addbashunit::helper::git::changed_filesandbashunit::helper::git::is_repo.src/helper/discovery.sh:208load_test_files— intersect discovery with the changed set.src/main/test.sh,src/config/env.sh(BASHUNIT_CHANGED),.env.example.
Acceptance criteria
-
--changedwith no argument diffs againstorigin/HEADwhen it resolves, otherwiseHEAD -
--changed maindiffs againstmain - Uncommitted and staged modifications to a test file are included
- Deleted test files are excluded (no "file not found" error)
- Renamed test files select the new path only
- Combines with
--filter/--tag(intersection) - Outside a git work tree: non-zero exit with an explicit message, not a full run
- An unresolvable ref: non-zero exit with the ref quoted in the message
- No changed test files: "No tests found" path, current exit code preserved
- Acceptance test builds a throwaway git repo in a temp dir (
bashunit::temp_dir), not the bashunit repo itself
Repo checklist (agent)
- TDD: RED → GREEN → REFACTOR. Write the failing test first.
- Bash 3.0+ only: no
printf -v, no+=append, nodeclare -A, no[[ ]], no${var,,}, no&>>, no${arr[-1]}. Expanding a possibly-empty array underset -uneeds${arr[@]+"${arr[@]}"}. - A new CLI flag must be wired in all of these or a parity test fails:
- parse in
src/main/test.sh(report-style flags needexport -n, seesrc/main/test.sh:188-196for why) - validate the value in
bashunit::main::validate_config_or_exit(src/main/validate.sh:60) — unvalidated input used to run the wrong thing and exit 0 (Unknown options are silently ignored: a typo'd flag runs a different suite and exits 0 #871, --jobs with a non-integer value hangs on Bash 3.x and is silently ignored on Bash 4.3+ #873) - default + env var in
src/config/env.shand a documented line in.env.example --helptext in the same block it belongs to- both
completions/bashunit.bashandcompletions/_bashunit(anti-drift test feat(cli): bash and zsh completion scripts with an anti-drift test #778 fails otherwise)
- parse in
- Gates:
make sa,make lint,./bashunit tests/,./bashunit --parallel tests/. Never runshfmt -w. - Docs: update
docs/command-line.md. Editingdocs/assertions.mdinvalidates thebashunit docacceptance snapshot — regenerate it. - CHANGELOG.md: add one line under
## Unreleased. - Fixtures under
tests/acceptance/fixtures/must not end in*test.sh. - One issue = one PR.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
Chemaclass commentedon Aug 10, 2026
Done in #1038 (merged).