LogPulse / guides

How to write release notes from commits (Conventional Commits)

Your commit history is the raw material for release notes, not the finished product. Conventional Commits give that raw material enough structure for a tool to draft a changelog, and you still edit the draft before it ships.

Updated Last checked 5 min readOpen-source libraries and packages

The short answer

  • Conventional Commits look like type(scope): description, with ! or a BREAKING CHANGE: footer for breaking changes.
  • feat maps to a minor version and an ‘Added’ line, fix to a patch and ‘Fixed’, and a breaking change to a major.
  • semantic-release, release-please and git-cliff turn these commits into a changelog; GitHub can generate notes from merged pull requests instead.
  • Edit the draft: merge related commits, drop internal ones (refactor, test, ci) and add migration steps.

Commit messages that produce good release notes

Each line below is the first line of a commit. The last commit adds a footer, separated from the summary by a blank line.

git log
feat(parser): add parseStream() for large inputs

fix: handle Windows (CRLF) line endings

feat!: require Node.js 20 or later

refactor(parser): split the tokenizer into smaller functions

feat(api): rename the timeout option to timeoutMs

BREAKING CHANGE: timeout was in seconds; timeoutMs is in
milliseconds. Replace timeout: 30 with timeoutMs: 30_000.

Changelog generators typically list the text after BREAKING CHANGE: under a breaking-changes heading, so write it as the migration step.

Free tool · no sign-up

Can a coding agent read your changelog?

Paste your repository, a GitHub release or a CHANGELOG.md link. The free converter shows every version, breaking change, migration step and deprecation it can extract, as JSON plus an llms.txt summary.

No AI and nothing stored. Or paste a CHANGELOG.md instead

01Why a raw commit log isn't release notes

A git log is written for reviewers. It includes refactors, test fixes, reverted experiments and ten commits for one feature. Keep a Changelog 2.0.0 puts it bluntly: “Do not use a list of commits as a changelog. It is full of noise.” It's just as direct about generated changelogs: “A generated changelog is raw material at best: a person still has to choose what is notable, group it, and write it for the reader.” The answer isn't to ignore commits; it's to give them enough structure that a tool can sort them, then edit the result.

02The Conventional Commits format

A Conventional Commits message starts with a type, an optional scope in parentheses and a description: fix(parser): handle CRLF line endings. A ! before the colon, or a footer starting with BREAKING CHANGE:, marks a breaking change. Types other than feat and fix are allowed; the Angular-based commitlint config, for example, recommends build, chore, ci, docs, style, refactor, perf and test.

CommitChangelog sectionSemVer bump
feat: …AddedMinor
fix: …FixedPatch
feat!: …, or any commit with a BREAKING CHANGE: footerChanged or Removed, marked **Breaking:** (generators often add a separate breaking-changes section instead)Major
perf: …Changed (often shown as Performance)Depends on your tool's configuration
docs, refactor, test, ci, choreUsually left outNone

The feat → minor, fix → patch and breaking → major mapping comes from the spec and lines up with Semantic Versioning.

03Tools that turn commits into a changelog

ToolWhat it doesA good fit when
semantic-releaseWorks out the next version from commits, then publishes the release, its notes and the package from CI. Uses the Angular commit conventions by default.You want every merge to the main branch released automatically.
release-pleaseOpens a release pull request that updates CHANGELOG.md and the version; merging it creates the GitHub release. It doesn't publish to package managers.You want a person to decide when to release, and to edit notes in the pull request.
git-cliffA configurable changelog generator for repositories that follow Conventional Commits.You want full control of the changelog format.
ChangesetsContributors add a small change file with a bump type and summary; at release time they're combined into versions and changelogs.Monorepos, or when commit messages aren't reliable.
GitHub generated release notesLists merged pull requests, contributors and a compare link, grouped by labels in .github/release.yml.Your team labels pull requests consistently.

For setup, monorepo support and what each one publishes, see semantic-release vs release-please vs Changesets. To pull a quick draft out of history without any tool, use plain git commands. For the GitHub release alone, the free LogPulse GitHub Action groups the commits since the last tag by type on every release, with BREAKING CHANGE: footers as migration steps. It's one workflow step, uses: kalmwerk/release-notes-action@v1 (on GitHub).

04Squash merges: the pull request title becomes the commit

If you squash-merge pull requests, the squashed commit message is what these tools read, not the commits inside the pull request. GitHub can default that message to the pull request title, so check titles against the convention during review, or with a CI check such as commitlint.

05Edit the draft before you publish

Generated notes are a first draft. Before you tag:

  1. Merge related commits into one line per user-visible change.
  2. Delete internal changes that slipped through: a fix to a test helper isn't a fix for users.
  3. Rewrite descriptions around what users notice. “Files with CRLF line endings now parse” beats “handle CRLF in lexer”.
  4. Add a migration step to every breaking change; a commit footer rarely has room for one.
  5. Add two or three highlights at the top of the GitHub release.

Then compare the result with the Markdown release notes templates and run the open-source release notes checklist.

Before and after

Too vague

Generated straight from the log: fix: lexer crlf · chore: deps · feat: stream · test: fixtures · feat: stream part 2

Specific and actionable

Added: parseStream() parses large files without loading them into memory (#412). Fixed: files with Windows (CRLF) line endings now parse correctly (#405).

Fictional example: use your own verified names, versions and behavior.

LogPulse

Generate release notes with LogPulse

LogPulse is a hosted changelog that people and coding agents can both read. Here's exactly what it can do for the steps above, and what it can't.

  1. Check your changelog, free

    Paste a CHANGELOG.md or a GitHub releases link. A deterministic parser (no AI, nothing stored) shows the versions, breaking changes, migration steps and deprecations an agent can extract.

    Open the converter

  2. Draft notes from GitHub

    Connect a repository: merged pull requests, commits to your default branch and published GitHub releases collect in an inbox. AI drafts a note in the tone you pick, listing breaking changes and deprecations only when the changes clearly show them. Nothing is published until you approve it. 3 AI drafts on Free; unlimited on Open source and Pro. Pro opens soon: .

    Free for open source

  3. Publish once, read everywhere

    Approved notes go to a hosted changelog and an in-app widget, to email subscribers on Open source and Pro (Pro opens soon), and to a JSON feed and MCP server coding agents can query. CI and agents can publish with an API key.

    Read the docs

What it doesn't do: LogPulse doesn't tag releases, bump versions, publish to npm or PyPI, or write CHANGELOG.md back to your repository; keep your release tooling for those. AI drafts can miss context, so review them like a pull request.

Before you publish

  • The commit (or pull request title) convention is documented in CONTRIBUTING.md
  • Every incompatible change uses ! or a BREAKING CHANGE: footer
  • The generated draft is edited: merged, trimmed and rewritten for users
  • Every breaking change has a migration step
  • The version bump matches the changes (major for anything breaking)

Common questions

Do I need Conventional Commits to generate release notes?

No. GitHub can generate notes from merged pull requests and labels, and Changesets uses change files instead of commit messages. Conventional Commits help most when you want both the version number and the changelog derived from history.

What if a contributor forgets the convention?

If you squash-merge, fix the pull request title before merging. Many projects add a CI check that lints pull request titles or commit messages; commitlint is a common choice.

Should chore and refactor commits appear in release notes?

Usually not, because nothing changes for users. If a refactor changes behavior or performance in a way people notice, describe that effect under Changed.

Can AI write release notes from my commits?

It can draft them. LogPulse's AI drafts read merged pull requests, commits and GitHub releases from a connected repository and write a note in the tone you choose; you review and approve it before anything is published. Treat any AI draft like a pull request and check each claim against the diff.

Sources

Facts last checked against these sources on .

More guides: open-source libraries and packages

All release notes guides

Tools and resources

LogPulse

Changelogs coding agents can upgrade from.

Publish versions, breaking changes, migration steps and deprecations once. People get a widget and hosted changelog; agents get a JSON feed and MCP server. Free for open source.