cz changelog picks the previous tag by date, not ancestry #2083
Description
Description
cz changelog treats the newest tag by creatordate as the previous release. That is wrong when two version lines are released in parallel.
get_tags() always sorts with --sort=-creatordate:
https://github.com/commitizen-tools/commitizen/blob/master/commitizen/git.py
get_tags() already has reachable_only (git tag --merged), but cz changelog calls git.get_tags() without it. get_next_tag_name_after_version() then returns the next name in that date-sorted list, even if it is not an ancestor of HEAD.
get_latest_tag_name() already uses ancestry (git describe --abbrev=0 --tags). Changelog generation does not.
Example
We maintain v4 and v5 on the same repo (espressif/esptool):
| Tag | Released |
|---|---|
v5.3.1 |
2026-06-29 |
v4.12.0 |
2026-07-14 |
v5.4.0 |
2026-09-02 |
cz changelog for v5.4.0 used v4.12.0 as the start tag (newer by date) and generated notes from v4.12.0 to v5.4.0 — i.e. most of the 5.x history, not just v5.3.1..v5.4.0.
git describe --abbrev=0 HEAD^ correctly yields v5.3.1.
Workaround
Pass --start-rev from the nearest ancestor tag:
CZ_ARGS=()
if PREVIOUS_TAG="$(git describe \
--tags \
--abbrev=0 \
HEAD^ \
--match 'v[0-9]*.[0-9]*.[0-9]*' \
--exclude '*.dev*' 2>/dev/null)"; then
CZ_ARGS=(--start-rev "${PREVIOUS_TAG}")
fi
cz changelog "${CZ_ARGS[@]}" --file-name changelog_body.mdExpected
The previous tag for a changelog should be the nearest reachable version tag (ancestry), not the newest tag by date.
Activity
fix(changelog): skip unreachable tags when picking previous release
fix(changelog): skip unreachable tags when picking previous release