Title: fix(bump): only consider commit titles when matching bump patterns by bearomorphism · Pull Request #1983 · commitizen-tools/commitizen · GitHub
Open Graph Title: fix(bump): only consider commit titles when matching bump patterns by bearomorphism · Pull Request #1983 · commitizen-tools/commitizen
X Title: fix(bump): only consider commit titles when matching bump patterns by bearomorphism · Pull Request #1983 · commitizen-tools/commitizen
Description: Description Closes #1772. Why cz bump was producing spurious PATCH version bumps on ci: commits whose bodies contained Dependabot-generated content. Dependabot's pull-request descriptions quote upstream repository changelogs verbatim, and those changelogs routinely contain lines such as fix: update @actions/artifact to ^5.0.0 for Node.js 24 punycode fix. Because find_increment in commitizen/bump.py:37 (master) iterates over every line of commit.message — which is computed as f"{self.title}\n\n{self.body}".strip() at commitizen/git.py:78–79 — those body lines are matched against the bump_pattern and counted as fix: commits, triggering a PATCH bump on a commit that is semantically a dependency-update automation entry with a ci: title. The issue was initially closed as "working as designed" after a maintainer misread the log: the fix: line in question was not a commit in the user's repository — it was text inside the Dependabot PR body (which becomes the body of the squash-merged ci: commit). @Clockwork-Muse clarified this with a screenshot in February 2026, and @Lee-W reopened the issue. Subsequent verification against master (4.15.1) in the #1964 audit confirmed the false positive is still reproducible: a ci: commit whose body contains an unbulleted fix: … line at column 0 produces a PATCH bump and a spurious ### Fix changelog section. The Conventional Commits specification places the commit type exclusively in the title (the first line); scanning every body line for type-prefixed text contradicts the spec and produces this class of false positive on auto-generated commit bodies. What changed File Change commitizen/bump.py In find_increment(), replace the commit.message.split("\n") loop at line 37 (master) with a candidate_lines list containing only commit.title plus any body lines that begin with BREAKING CHANGE: or BREAKING-CHANGE: tests/test_bump_find_increment.py Add two regression tests: test_find_increment_ignores_type_tokens_in_commit_body (the Dependabot false-positive scenario) and test_find_increment_still_honors_breaking_change_in_body (confirming MAJOR is still triggered by a body footer) How it works Title-only type matching: candidate_lines is initialised as [commit.title]. The commit.title attribute stores only the first line of the commit message (set at commitizen/git.py:71), so no body content can reach the bump_pattern via this path. Body still scanned for breaking-change footers: the body is split on "\n" and each line is tested with stripped.startswith(("BREAKING CHANGE:", "BREAKING-CHANGE:")) after a lstrip() call. Matching lines are appended to candidate_lines and then processed by the same select_pattern.search() call as the title. lstrip() rather than strip() for footer indentation tolerance — the non-obvious choice: the Conventional Commits spec allows trailers to be indented (e.g., BREAKING CHANGE: x). Using lstrip() means such indented footers are still accepted, while a body line like fix: something is stripped to fix: something, which does not start with either breaking-change token and so is correctly excluded. Using strip() instead would also work here, but lstrip() is semantically more precise — the trailing content of a footer is not guaranteed to be whitespace-free, so only left-stripping is warranted for the prefix check. commit.message property untouched: commitizen/git.py:77–79 defines message as title + "\n\n" + body and this property is used elsewhere (changelog rendering, the check command). Only find_increment changes which lines it examines; every other consumer of commit.message is unaffected. Backward compatibility Any commit whose title begins with a conventional type (fix:, feat:, perf:, etc.) is still bumped exactly as before. BREAKING CHANGE: / BREAKING-CHANGE: footers in the commit body still trigger a MAJOR bump. The feat!: / fix!: exclamation-mark breaking-change syntax in the title is unaffected — it is matched against commit.title by the same select_pattern. commit.message, commit.title, and commit.body on GitCommit (commitizen/git.py:60–79) are untouched. All 12 pre-existing test_find_increment_* tests in tests/test_bump_find_increment.py pass; the full bump command integration test suite (131 tests) passes with the same 4 GPG-fixture tests deselected on Windows as before. Checklist I have read the contributing guidelines Was generative AI tooling used to co-author this PR? Yes (please specify the tool below) Generated-by: Claude 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 (see "Steps to Test" below) Update the documentation for the changes Expected Behavior Scenario Outcome ci: commit whose body contains fix: … lines (Dependabot-style) No bump — body type-prefixed lines are ignored fix: normal patch fix in the commit title PATCH bump — unchanged feat: new feature title with BREAKING CHANGE: old API removed in the body MAJOR bump — breaking-change footer still honoured feat!: breaking change flagged in title MAJOR bump — exclamation-mark syntax in title still honoured ci: commit with a bulleted body line - fix: addresses CVE-… No bump — leading - prevents startswith match and the line is excluded Steps to Test This Pull Request git fetch fork fix/1772-anchor-bump-pattern-to-title git checkout fork/fix/1772-anchor-bump-pattern-to-title # 1. Targeted regression test. uv run pytest tests/test_bump_find_increment.py -v # 2. Reproduce-the-bug-then-verify-the-fix sequence. python - <<'EOF' from commitizen import bump from commitizen.git import GitCommit from commitizen.cz.conventional_commits import ConventionalCommitsCz # Exact reproducer from #1772: a ci: commit whose body quotes an upstream # changelog entry containing "fix: ..." at column 0. DEPENDABOT_BODY = ( "Bumps actions/upload-artifact from 5 to 6.\n" "fix: update @actions/artifact to ^5.0.0 for Node.js 24 punycode fix\n" ) commit = GitCommit( rev="abc123", title="ci: bump actions/upload-artifact from 5 to 6 (#23)", body=DEPENDABOT_BODY, ) result = bump.find_increment( [commit], regex=ConventionalCommitsCz.bump_pattern, increments_map=ConventionalCommitsCz.bump_map, ) assert result is None, f"FAIL: expected None, got {result!r} — false-positive bump still present" print("OK: Dependabot body does not trigger a bump") # Confirm BREAKING CHANGE in body still works. bc_commit = GitCommit( rev="def456", title="feat: new user interface", body="some detail\n\nBREAKING CHANGE: drops support for legacy config format", ) result = bump.find_increment( [bc_commit], regex=ConventionalCommitsCz.bump_pattern, increments_map=ConventionalCommitsCz.bump_map, ) assert result == "MAJOR", f"FAIL: expected MAJOR, got {result!r}" print("OK: BREAKING CHANGE footer still triggers MAJOR") EOF Additional Context This fix was surfaced during the #1964 issue audit. The issue had been incorrectly closed in February 2026 after a maintainer misidentified the fix: line as a commit in the user's own repository; @Clockwork-Muse's follow-up comment and screenshot clarified that the line comes from Dependabot quoting an upstream changelog entry — it is not a commit in the user's repository at all. @namwoam was assigned in January 2026 and identified the correct code path (commitizen/bump.py:37–38, master) but proposed an author-filter approach; this PR takes the simpler route of anchoring the type match to the commit title only, which aligns with the Conventional Commits specification without introducing new configuration surface. @namwoam is welcome to take over if still active on this — please comment and this PR will be closed.
Open Graph Description: Description Closes #1772. Why cz bump was producing spurious PATCH version bumps on ci: commits whose bodies contained Dependabot-generated content. Dependabot's pull-request descriptions quote...
X Description: Description Closes #1772. Why cz bump was producing spurious PATCH version bumps on ci: commits whose bodies contained Dependabot-generated content. Dependabot's pull-request descriptions q...
Opengraph URL: https://github.com/commitizen-tools/commitizen/pull/1983
X: @github
Domain: github.com
| route-pattern | /:user_id/:repository/pull/:id/files(.:format) |
| route-controller | pull_requests |
| route-action | files |
| fetch-nonce | v2:bcfa8042-e87f-c198-181d-bac8f4883045 |
| current-catalog-service-hash | ae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b |
| request-id | 8FDC:179658:78BD86:B2728A:6A4E1526 |
| html-safe-nonce | 1650a6bef2d8eeda6fdaeb4e1ea57c9ffa116d8b1c21ac6ea2851faabb9af2be |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4RkRDOjE3OTY1ODo3OEJEODY6QjI3MjhBOjZBNEUxNTI2IiwidmlzaXRvcl9pZCI6IjQ1ODA1MDM5NDM0NjE2MDY2OTQiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 37117d27f8f19061b44fd36a2d945a2f5536fa4454d63a902771c0e574fd5582 |
| hovercard-subject-tag | pull_request:3654893121 |
| github-keyboard-shortcuts | repository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/commitizen-tools/commitizen/pull/1983/files |
| twitter:image | https://avatars.githubusercontent.com/u/26526132?s=400&v=4 |
| twitter:card | summary_large_image |
| og:image | https://avatars.githubusercontent.com/u/26526132?s=400&v=4 |
| og:image:alt | Description Closes #1772. Why cz bump was producing spurious PATCH version bumps on ci: commits whose bodies contained Dependabot-generated content. Dependabot's pull-request descriptions quote... |
| og:site_name | GitHub |
| og:type | object |
| hostname | github.com |
| expected-hostname | github.com |
| None | 030096ee0db095447bfe77409d33bfac127ca7128299c58deef27c52eaa1b1f0 |
| turbo-cache-control | no-preview |
| diff-view | unified |
| go-import | github.com/commitizen-tools/commitizen git https://github.com/commitizen-tools/commitizen.git |
| octolytics-dimension-user_id | 62252524 |
| octolytics-dimension-user_login | commitizen-tools |
| octolytics-dimension-repository_id | 106127589 |
| octolytics-dimension-repository_nwo | commitizen-tools/commitizen |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 106127589 |
| octolytics-dimension-repository_network_root_nwo | commitizen-tools/commitizen |
| turbo-body-classes | logged-out env-production page-responsive full-width |
| disable-turbo | true |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | ea9187571e3edc5f2780f750631138669441ca50 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width