fix(git/log): stop dropping merge commits when user pins a selection#2016
Open
YOMXXX wants to merge 1 commit into
Open
fix(git/log): stop dropping merge commits when user pins a selection#2016YOMXXX wants to merge 1 commit into
YOMXXX wants to merge 1 commit into
Conversation
`rtk git log -1 HEAD` on a repo whose HEAD is a `--no-ff` merge commit M (parents [P1, P2]) was returning P2 instead of M. Same for explicit SHAs, annotated tags, `--graph`, and `--graph --oneline` — every shape that names a specific commit got the second parent of the merge instead of the merge itself. Caller can't tell the result is wrong because P2 is a real recent commit. Root cause: `run_log` unconditionally injects `--no-merges` as a token-saving default. When the user passes `-1`, git walks past the dropped merge to the next non-merge commit (the second parent because git log defaults to a topology-aware traversal), so a precise pin silently shifts the selection. `--no-merges` is the right default only when RTK is fully driving the output — bare `git log` with no flags, no ref, no format. As soon as the user signals "I'm picking", the default has to stand down. Extract `should_add_no_merges_default(args, has_format, has_limit)` as a pure helper. Returns `true` only when none of these signals are present: - `--format` / `--pretty` / `--oneline` (caller controls output shape) - `-N` / `-n N` / `--max-count=N` (caller picked a precise window) - `--graph` (caller wants topology — needs merges) - any positional argument (ref / SHA / tag / pathspec) - explicit `--merges` / `--min-parents=2` (caller already opted in) `has_format` and `has_limit` are passed in from the caller's existing scan so we don't re-walk the args list. Behaviour matrix (existing tests stayed green, the new ones pin each shape): | invocation | --no-merges? | |---------------------------------------|--------------| | `rtk git log` | yes (RTK default) | `rtk git log -1 HEAD` | no (rtk-ai#2009 fix) | `rtk git log -1` | no | `rtk git log --format=%H HEAD` | no | `rtk git log <sha>` | no | `rtk git log --graph` | no | `rtk git log --graph --oneline` | no | `rtk git log --merges` | no (explicit opt-in) | `rtk git log --min-parents=2` | no | `rtk git log --author=foo` | yes (filter, not a pin) | `rtk git log --max-count=5` | no Tests: - test_no_merges_added_for_bare_git_log — token-saving default stays. - test_no_merges_skipped_with_explicit_limit_one + _only — covers `-1 HEAD` and bare `-1`, the headline reproduction from rtk-ai#2009. - test_no_merges_skipped_with_format_flag_and_ref + _explicit_sha + _graph_flag + _graph_and_oneline — covers every other shape the issue body called out as broken. - test_no_merges_skipped_with_explicit_merges + _min_parents — locks in the pre-existing opt-in semantics so the refactor doesn't regress it. - test_no_merges_still_added_with_author_filter — documents the deliberate narrow scope: filter flags that don't pick a single commit still benefit from the token-saving default. - test_no_merges_skipped_with_max_count_arg — short-circuit via has_limit. cargo fmt / clippy --all-targets / test --bin rtk: 1920 passed, 0 warnings. Fixes rtk-ai#2009
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.
Summary
`rtk git log -1 HEAD` on a repo whose HEAD is a `--no-ff` merge commit M (parents `[P1, P2]`) returns P2 instead of M. Same for explicit SHAs, annotated tags, `--graph`, and `--graph --oneline` — every shape that names a specific commit gets the second parent of the merge instead of the merge itself.
The caller can't tell the result is wrong, because P2 is a real recent commit. A release script that asks "what's the SHA of the merge I just landed?" gets a value that looks plausible and is wrong.
`rtk proxy git log -1 HEAD` returns M, confirming `git` itself is fine — the bug is in RTK's filter.
Root cause
`run_log` in `src/cmds/git/git.rs` unconditionally injects `--no-merges` as a token-saving default. When the user passes `-1`, git walks past the dropped merge to the next non-merge commit (the second parent, because `git log` defaults to a topology-aware traversal), so the precise pin silently shifts the selection.
`--no-merges` is the right default only when RTK is fully driving output — bare `git log` with no flags, no ref, no format. As soon as the user signals "I'm picking", the default has to stand down.
Fix
Extract a pure helper `should_add_no_merges_default(args, has_format, has_limit)`. It returns `true` only when none of these signals are present:
`has_format` and `has_limit` are passed in from the caller's existing scan so we don't re-walk the args list.
Behaviour matrix
Test plan
11 new tests pin each shape in the table above:
`cargo fmt --all` clean / `cargo clippy --all-targets` zero warnings / `cargo test --bin rtk -- --test-threads=8` → 1920 passed (was 1909).
Scope notes
Fixes #2009