Skip to content

fix: honor explicit -n N limit for git log on merge commits#2015

Merged
aeppling merged 2 commits into
rtk-ai:developfrom
Arvuno:contrib/rtk/git-log-merge-fix
May 23, 2026
Merged

fix: honor explicit -n N limit for git log on merge commits#2015
aeppling merged 2 commits into
rtk-ai:developfrom
Arvuno:contrib/rtk/git-log-merge-fix

Conversation

@Arvuno
Copy link
Copy Markdown

@Arvuno Arvuno commented May 21, 2026

No description provided.

When user runs 'git log -1 --format='%H' HEAD' where HEAD is a merge
commit, rtk was adding --no-merges which filtered out the merge commit
itself and returned the second parent instead. This made 'git log -1'
return wrong SHAs for merge commits.

Fix: don't add --no-merges when user explicitly passes -n N or
--max-count=N. When a user specifies an exact count they expect exactly
that many commits, not filtered results. Also skip --no-merges if user
already passed --merges or --no-merges explicitly.

Fixes rtk-ai#2009.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 21, 2026

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ aeppling
❌ okwn
You have signed the CLA already but the status is still pending? Let us recheck it.

@aeppling
Copy link
Copy Markdown
Contributor

Hey, pretty straightforward

Thanks for contributing to RTK !

@aeppling aeppling self-assigned this May 22, 2026
@aeppling aeppling merged commit 26c8890 into rtk-ai:develop May 23, 2026
10 of 11 checks passed
@aeppling aeppling mentioned this pull request May 23, 2026
YOMXXX added a commit to YOMXXX/rtk that referenced this pull request May 26, 2026
…ions

Builds on the partial fix in rtk-ai#2015 (which honoured `-n N` /
`--max-count=N`). rtk-ai#2015 closed rtk-ai#2009 but only covered count-based
pinning; this PR extends the same idea to every remaining shape from
the issue's reproduction:

| invocation                            | upstream | this PR |
|---------------------------------------|----------|---------|
| `rtk git log`                         | default  | default
| `rtk git log -1 HEAD`                 | wrong*   | fixed
| `rtk git log -1`                      | default  | default
| `rtk git log --format=%H HEAD`        | wrong*   | fixed
| `rtk git log <sha>`                   | wrong*   | fixed
| `rtk git log --graph`                 | wrong*   | fixed
| `rtk git log --graph --oneline`       | wrong*   | fixed
| `rtk git log --merges`                | wrong*   | fixed (opt-in)
| `rtk git log --min-parents=2`         | wrong*   | fixed (opt-in)
| `rtk git log --author=foo`            | default  | default
| `rtk git log --max-count=5`           | fixed    | fixed (via rtk-ai#2015)

*wrong = `--no-merges` silently injected even though the user pinned a
specific selection. On a `--no-ff` merge commit M (parents [P1, P2]),
git log walks past the dropped merge and returns P2 — a real, recent,
plausible, but wrong SHA. Caller can't tell the result is wrong because
P2 looks valid.

Root cause: `run_log` was unconditionally injecting `--no-merges` as a
token-saving default. `--no-merges` is the right default only when RTK
is fully driving the output (bare `git log`, no flags, no ref, no
format). As soon as the user signals "I'm picking", the default has
to stand down.

This PR extracts `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 window — rtk-ai#2015)
- `--graph`                               (caller wants topology)
- 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.

Tests (11 new):
- 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.
- 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 (overlaps with rtk-ai#2015 to lock the contract in tests).

cargo +1.93.0 fmt / clippy --all-targets / test --bin rtk:
1957 passed, 0 warnings.

Refs rtk-ai#2009 (closed by rtk-ai#2015 for `-n N`; this completes the other shapes)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants