Skip to content

fix: resolve semantic commit range by ancestry (fixes #86) - #87

Merged
SebastianKuesters merged 2 commits into
mainfrom
fix/issue-86-ancestry-commit-range
Aug 25, 2026
Merged

SebastianKuesters merged 2 commits into
mainfrom
fix/issue-86-ancestry-commit-range

Conversation

@SebastianKuesters

Copy link
Copy Markdown
Member

Summary

get_new_commits() walked the history in reverse commit date order and stopped at the commit the previous tag pointed at. When a branch stays open across another release, its commits are older than the new tag, so the date-ordered walk reached the tag first and never analysed them — silently dropping feat!: / BREAKING CHANGE: commits from the version calculation. This caused a breaking change to be released as a minor. Fixes #86.

Change

  • Resolve the commit range by ancestry using git rev-list HEAD ^<reference_tag> instead of a date-ordered walk with manual paging. This is unaffected by commit dates and drops the max_commits/skip loop.
  • Also exclude commits reachable from the current channel's own latest tag. This keeps the hotfix model correct: cherry-picked hotfix commits already released on a channel are not reachable from the (cross-channel) reference tag, and the pure ancestry range would otherwise re-count them and produce spurious hotfix bumps.

Tests

  • Added tests/e2e/test_long_running_branch.py: regression test where a feat!: on a branch that stays open across another release must still bump the major version (v0.0.1 → v1.0.0).
  • Full e2e suite: 48/48 passing, including all hotfix scenarios.
  • mypy, flake8, pylint clean (pylint 10.00/10).

get_new_commits() walked history in reverse commit-date order and stopped
at the commit the previous tag pointed at. A branch that stays open across
another release has commits older than the newer tag, so the date-ordered
walk reached the tag first and never analysed them - silently dropping
feat!:/BREAKING CHANGE: commits from the version calculation (issue #86).

Resolve the range by ancestry via `git rev-list HEAD ^<reference_tag>`
instead. To keep the hotfix model working, also exclude commits reachable
from the current channel's own latest tag, so cherry-picked hotfixes that
are already released on this channel are not counted again.

Fixes #86

Co-authored-by: Copilot App <[email protected]>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Fixes semantic version calculation by resolving unreleased commits through Git ancestry.

Changes:

  • Replaces date-ordered history traversal with git rev-list.
  • Excludes commits reachable from reference and channel tags.
  • Adds a long-running branch regression test.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
semantic.py Implements ancestry-based commit selection.
test_long_running_branch.py Tests detection of older breaking commits.

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

Comment on lines +122 to +125
rev_list_args = [repo.head.commit.hexsha, *(f'^{sha}' for sha in exclude)]

try:
output = repo.git.rev_list(*rev_list_args)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch — fixed in 16e72ec. Moved the repo.head.commit resolution inside the try so an empty repository (no HEAD commit) again logs and returns [] instead of raising.

Comment on lines +127 to +129
except (ValueError, git.GitCommandError) as exc:
logger.warning('No commits found: %s', exc)
return []

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed — fixed in 16e72ec. Now only ValueError (missing HEAD) is caught; git.GitCommandError from git rev-list propagates so a real command failure isn't silently reported as no semantic changes.

…rev-list errors

- Move `repo.head.commit` resolution inside the try so an empty repository
  (no HEAD commit) still logs and returns [] instead of raising.
- Only catch ValueError (missing HEAD). Let git.GitCommandError from
  `git rev-list` propagate, so a genuine command failure is not silently
  reported as "no semantic changes".

Co-authored-by: Copilot App <[email protected]>
@SebastianKuesters
SebastianKuesters merged commit 566de1c into main Aug 25, 2026
8 checks passed
@SebastianKuesters
SebastianKuesters deleted the fix/issue-86-ancestry-commit-range branch August 25, 2026 11:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

semantic mode misses breaking commits older than the previous tag (date-ordered walk stops early)

2 participants