feat: filter reviews by commit author, date, message and branch - #25
Merged
Conversation
`git diff` has no --author/--since/--until/--grep — those are `git log`
options — so a filter that selects commits cannot ride the normal
diff-acquisition path. Add a commit-selection layer behind the existing
`fetchDiff` seam, plus the path denylist that was missing next to
--file/--dir.
New global flags:
--author / --committer name or email, case-insensitive; repeatable
--start-date/--end-date strict YYYY-MM-DD, both ends inclusive
--text commit message, and branch names
--max-commits / --merges modifiers; error if used alone
--exclude-file/--exclude-dir path denylist, --file/--dir rules inverted
AND across filter kinds, OR within one kind.
internal/git/select.go runs a two-phase select-then-show: a `git log`
metadata walk, an optional for-each-ref + rev-list pass for branch-name
hits, then `git show -m --first-parent` for exactly the chosen hashes.
Three decisions worth recording:
- Identity and text matching happen in Go, not git. `git log --author=A
--grep=B` ORs the two by default, and --all-match would then also AND
multiple --author values together, breaking OR-within-a-kind.
- `git show`, not `git log -p`. The latter indents the commit body four
spaces, and internal/diff's parser reads a leading-space line as hunk
context, so a message body would be silently absorbed into the
previous hunk.
- The patches are concatenated, not reduced to one cumulative A..B diff.
A cumulative diff would include every unmatched commit in between,
making the filter a lie. The cost is that a file touched by three
matching commits appears three times.
--end-date is expanded to 23:59:59 so the named day is included; git's
bare --until stops at that day's midnight and drops it.
Scope: no positional range walks HEAD, bounded by --max-commits; a
subcommand's range bounds it instead. Conflicts with --staged/--unstaged,
which have no commits. Rejected by `commit` (describes the staged index)
and `remote pr` (its diff comes from `gh pr diff`).
Also carries the filters across the MCP/guard seam, which resets the
global flag state — this makes --file/--dir reachable there for the
first time. Adds meta.filtered_commits (omitempty, schema stays 1) and
commit/exclusion accounting to dry-run. No cache-key change: the key
already hashes the post-filter diff text.
Fixes: `remote pr` now applies --file/--dir on the posting path too, not
only under --no-post.
Docs: ADR-0035, contracts/{cli-surface,json-schema-v1,cache-key},
TECHNICAL_ARCHITECTURE, architecture/{overview,diagrams}, PRD, README,
CHANGELOG, man pages.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
git diffhas no --author/--since/--until/--grep — those aregit logoptions — so a filter that selects commits cannot ride the normal diff-acquisition path. Add a commit-selection layer behind the existingfetchDiffseam, plus the path denylist that was missing next to --file/--dir.New global flags:
--author / --committer name or email, case-insensitive; repeatable
--start-date/--end-date strict YYYY-MM-DD, both ends inclusive
--text commit message, and branch names
--max-commits / --merges modifiers; error if used alone
--exclude-file/--exclude-dir path denylist, --file/--dir rules inverted
AND across filter kinds, OR within one kind.
internal/git/select.go runs a two-phase select-then-show: a
git logmetadata walk, an optional for-each-ref + rev-list pass for branch-name hits, thengit show -m --first-parentfor exactly the chosen hashes.Three decisions worth recording:
git log --author=A --grep=BORs the two by default, and --all-match would then also AND multiple --author values together, breaking OR-within-a-kind.git show, notgit log -p. The latter indents the commit body four spaces, and internal/diff's parser reads a leading-space line as hunk context, so a message body would be silently absorbed into the previous hunk.--end-date is expanded to 23:59:59 so the named day is included; git's bare --until stops at that day's midnight and drops it.
Scope: no positional range walks HEAD, bounded by --max-commits; a subcommand's range bounds it instead. Conflicts with --staged/--unstaged, which have no commits. Rejected by
commit(describes the staged index) andremote pr(its diff comes fromgh pr diff).Also carries the filters across the MCP/guard seam, which resets the global flag state — this makes --file/--dir reachable there for the first time. Adds meta.filtered_commits (omitempty, schema stays 1) and commit/exclusion accounting to dry-run. No cache-key change: the key already hashes the post-filter diff text.
Fixes:
remote prnow applies --file/--dir on the posting path too, not only under --no-post.Docs: ADR-0035, contracts/{cli-surface,json-schema-v1,cache-key}, TECHNICAL_ARCHITECTURE, architecture/{overview,diagrams}, PRD, README, CHANGELOG, man pages.
Summary
Related issues
Type of change
Test plan
make lint testpasses locallyNotes for reviewers
Checklist
internal/i18n(no hard-coded text).commitbrief listoutput has been updated accordingly.