Maintenance branch vs prerelease branch in semantic-release for backporting a fix
0 reputation · 14 Nov 2025, 09:32 UTC
0 reputation · 14 Nov 2025, 09:32 UTC
Our project uses semantic-release with Conventional Commits, and we need to ship a bug fix to users still on the 1.x line while main has already moved to 2.x. The documented options are a maintenance branch (e.g., 1.x) that publishes real patch versions, or a prerelease branch (e.g., beta) that publishes dist-tagged prereleases consumers must opt into.
During a trial run, CI completed without error but nothing was published, and we cannot tell from the logs alone whether the branch configuration failed to match, or whether the analyzed commits simply contained no release-triggering type. The research notes that branch syntax changed across major versions, so config copied from older guides may silently match nothing.
Assume a recent semantic-release major version; exact branch syntax should be verified against the installed version's docs.
30275 reputation · 14 Nov 2025, 12:42 UTC
For backporting a bug fix to an older major version (e.g., 1.x) while the main line has progressed to 2.x, a maintenance branch is the correct choice. A prerelease branch is intended for upcoming unstable features, not for supporting legacy stable versions.
| Feature | Maintenance Branch (e.g., 1.x) |
Prerelease Branch (e.g., beta) |
|---|---|---|
| Version Result | Stable patch (e.g., 1.2.1) |
Prerelease tag (e.g., 1.2.1-beta.1) |
| Distribution | Published to latest or specific tag |
Published to a dist-tag (e.g., @beta) |
| Consumer Impact | Standard update via semver range | Requires explicit opt-in to the prerelease tag |
When CI completes without error but no package is published, you must distinguish between a configuration mismatch and a lack of triggering commits. Assuming a recent version of semantic-release, check your logs for these specific patterns:
"No release branches found" or the process will exit immediately after the initial environment check without entering the analysis phase."No relevant changes found" or "No release to be published" after listing the commits it analyzed.Verification: Run the release with the DRY_RUN=true environment variable. This will explicitly log which branch is being targeted and which commits are being parsed without performing the actual publish.
Squashing a backport commit does not change which commits are analyzed, but it does change the analysis result. semantic-release analyzes the commit history between the last Git tag on that branch and the current HEAD.
fix: commit into a generic merge: or chore: commit, the release will not be triggered.fix: resolve memory leak), it will trigger the patch release normally.Missing Diagnostic: Please provide the branches array from your .releaserc or package.json configuration. If the syntax uses an outdated format (e.g., from v10 or earlier), the branch may be silently ignored by newer versions of the tool.
Use comments to ask for clarification. Post a solution as an answer.
30,275 reputation · 14 Nov 2025, 10:24 UTC
To address the question regarding squashing: semantic-release analyzes the commit history between the last git tag on that specific branch and the current HEAD. If you squash a backport commit during a merge or rebase, the tool only sees the final resulting commit message.
This is critical for maintenance branches because:
fix: prefix but the squash commit uses a generic message like Merge branch 'main' into 1.x, semantic-release will not trigger a release.For those troubleshooting "no release" scenarios in recent versions, running the process with the DEBUG=semantic-release:* environment variable will provide a detailed trace of which commits were analyzed and why they were skipped.