Skip to content

fix(changelog): skip unreachable tags when picking previous release (#2083) - #2085

Open
nehraa wants to merge 1 commit into
commitizen-tools:masterfrom
nehraa:fix/2083-changelog-ancestry
Open

fix(changelog): skip unreachable tags when picking previous release (#2083)#2085
nehraa wants to merge 1 commit into
commitizen-tools:masterfrom
nehraa:fix/2083-changelog-ancestry

Conversation

@nehraa

@nehraa nehraa commented Sep 11, 2026

Copy link
Copy Markdown

Description

cz changelog <version> resolves the previous-release tag by walking the creatordate-sorted tag list. When a parallel maintenance branch carries a tag with a creatordate between the current release and the legitimate previous release, that branch's tag was wrongly picked — it was reachable from some commit, just not from HEAD.

get_tags() already supports a reachable_only flag that appends git tag --merged. This change passes that flag from the changelog path so unreachable parallel-line tags are filtered out before the sort, matching the behaviour of get_latest_tag_name(), which already uses git describe --abbrev=0 --tags (ancestry-based) for the same reason.

Repro (espressif/esptool from the issue body): a parallel v4 line carried 4.12.0 whose creatordate was between 5.3.1 and 5.4.0. cz changelog 5.4.0 resolved the previous-release tag to 4.12.0 instead of 5.3.1, then generated notes from 4.12.0 to 5.4.0 because get_next_tag_name_after_version walks the date-sorted list and 4.12.0 sits next to 5.4.0.

Fixes #2083

Checklist

Was generative AI tooling used to co-author this PR?

  • Yes (please specify the tool below)

Generated-by: Claude Code following the guidelines

Code Changes

  • Add test cases to all the changes you introduce
  • Run uv run poe all locally to ensure this change passes linter check and tests
  • Manually test the changes:
    • Verify the feature/bug fix works as expected in real-world scenarios
    • Test edge cases and error conditions
    • Ensure backward compatibility is maintained
    • Document any manual testing steps performed
  • Update the documentation for the changes

Documentation Changes

@codecov

codecov Bot commented Sep 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.26%. Comparing base (d914b4d) to head (429973b).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2085      +/-   ##
==========================================
+ Coverage   98.19%   98.26%   +0.07%     
==========================================
  Files          61       61              
  Lines        2829     2832       +3     
==========================================
+ Hits         2778     2783       +5     
+ Misses         51       49       -2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Explicit version-range handling remains affected, and the regression test and documentation nits need updates.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Fixes changelog previous-release selection by excluding unreachable parallel-branch tags.

Changes:

  • Filters changelog tags by reachability from HEAD.
  • Adds regression coverage for parallel maintenance branches.
File summaries
File Summary
commitizen/commands/changelog.py Adds reachability filtering. Moderate (1 vote): this also breaks explicit version ranges on other branches and needs narrower handling.
tests/commands/test_changelog_command.py Adds regression setup. Nits (3 votes each): exercise the command path directly and add the required nested-function docstring.
Review details

Suppressed comments (1)

commitizen/commands/changelog.py:214

  • Using --merged here also filters the tags needed to resolve an explicit positional range. get_oldest_and_newest_rev looks up both versions from tags, so cz changelog 4.11.0..4.12.0 run while HEAD is on another release branch will now raise NoCommitsFoundError, even though the documented command supports version ranges and Git can read those refs. Restrict reachability filtering to implicit previous-release lookup, or resolve explicit ranges against their requested end revision.
        tags = self.tag_rules.get_version_tags(
            git.get_tags(reachable_only=True), warn=True
        )
  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

# env afterward so subsequent ``util.tick`` keeps working.
from commitizen import cmd as _cmd

def _tag_at(tag, iso_date):

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: added docstring to _tag_at in the amended commit.

Comment on lines +1760 to +1761
start_rev, end_rev = get_oldest_and_newest_rev(
cz_git.get_tags(reachable_only=True), "5.4.0", rules

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the amended commit. The test now goes through util.run_cli (cz changelog) and uses monkeypatch to spy on the production call site commitizen.commands.changelog.git.get_tags. If the production change is reverted, the spy assertion fails because the call no longer passes reachable_only=True.

@nehraa
nehraa force-pushed the fix/2083-changelog-ancestry branch from 46c82fc to 828393f Compare September 11, 2026 05:24
`cz changelog <version>` resolves the previous-release tag by walking
the creatordate-sorted tag list. When a parallel maintenance branch
carries a tag whose creatordate sits between the current release and
the legitimate previous release, that branch's tag was wrongly
picked because it was reachable from some commit, just not from HEAD.

`get_tags()` already supports a `reachable_only` flag that appends
`git tag --merged`. Pass it from the changelog path so unreachable
parallel-line tags are filtered out before the sort, mirroring the
behaviour of `get_latest_tag_name()` which already uses
`git describe --abbrev=0 --tags` (ancestry-based) for the same
reason.

Fixes commitizen-tools#2083
@nehraa
nehraa force-pushed the fix/2083-changelog-ancestry branch from 828393f to 429973b Compare September 11, 2026 06:02
@nehraa

nehraa commented Sep 11, 2026

Copy link
Copy Markdown
Author

Suppressed comment addressed: the reachability filter is now scoped to the implicit previous-release lookup path only. Explicit X..Y ranges now call git.get_tags() (unfiltered) so tag resolution by name still works when HEAD is on an unrelated branch.

Added test_changelog_explicit_rev_range_when_head_on_unrelated_branch (orphan-branch fixture, asserts the explicit range still resolves and renders the main-line commits) — fails on the previous broad fix, passes on the narrowed one. Full suite: 1309 passed.

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.

cz changelog picks the previous tag by date, not ancestry

3 participants