Free tool · no sign-up · runs in your browser

Generate a changelog from your git commits.

Paste git log output or Conventional Commits. You get a Keep a Changelog section, sorted into Added, Changed, Fixed, Removed and Security with breaking changes flagged, and the same changes as plain release notes.

Blank for [Unreleased]

Only used with a version

owner/repo or a GitLab URL: links versions and #123

Runs in your browser. Nothing you paste is uploaded or stored.

Short guide

How to generate a changelog from git commits

Your history already knows what changed between two releases. Three steps turn it into a changelog: find the previous release, copy the commits since then, and edit what the tool sorted for you. Editing matters: Keep a Changelog 2.0.0 says plainly “Do not use a list of commits as a changelog”, because a commit records a step in the code and a changelog entry records what changed for the people using it.

1. Find the previous release and list the commits since then

git describe --tags --abbrev=0 prints the most recent tag reachable from where you are (--tags includes lightweight tags). A..B means the commits in B that aren't in A, so v1.4.0..HEAD is everything since 1.4.0. --no-merges leaves out merge commits.

The range since the last tag
# The previous release: the most recent tag reachable from HEAD
git describe --tags --abbrev=0
# v1.4.0

# Commits since then, one line each (tags shown)
git log v1.4.0..HEAD --oneline --no-merges --decorate

# Full messages, so BREAKING CHANGE: footers come along
git log v1.4.0..HEAD --no-merges

2. Copy them straight to your clipboard

One command finds the tag and copies everything since it. Paste the result into the box above.

Since the last tag, to the clipboard
# macOS
git log "$(git describe --tags --abbrev=0)..HEAD" --no-merges | pbcopy

# Linux (X11, with xclip installed)
git log "$(git describe --tags --abbrev=0)..HEAD" --no-merges | xclip -selection clipboard

# Windows PowerShell
git log "$(git describe --tags --abbrev=0)..HEAD" --no-merges | Set-Clipboard
Other git log ranges
When you wantRun
Exactly what went into one past releasegit log v1.3.0..v1.4.0 --no-merges
A first release, before any tagsgit log --no-merges
One entry per merged pull request (merge-commit workflow)git log v1.4.0..HEAD --first-parent
The last 50 commits with tags shown; the tool stops at the previous release's taggit log -50 --oneline --decorate

3. Paste, then edit

The tool sorts each commit into a type of change, flags breaking changes and leaves out merges, release commits and chores. Then it's your turn: merge lines that describe one change, drop what users won't notice, and add upgrade steps where something breaks. As Keep a Changelog puts it, “machines can draft, but humans curate.”

The mapping

How Conventional Commits map to changelog sections

The same rules as the free GitHub Action and GitLab component, so what you see here is what they write into your releases.

Commit types and the Keep a Changelog section each one goes to
feat: feature:AddedA new feature: a minor version under SemVer.feat: add dark mode
fix: bugfix: hotfix:FixedA bug fix: a patch version.fix: handle empty input
perf: refactor: revert:ChangedChanges to how something that exists behaves.perf: cache parsed configs
security:SecurityVulnerabilities, so people know to upgrade.security: redact tokens in logs
deprecate:DeprecatedSay which version removes it, in the entry.deprecate: the legacy option
remove:RemovedUsually breaking too: add a !.remove: the v1 endpoints
! before the colon, or a BREAKING CHANGE: footerIts own type, marked Breaking: in placeFooter text becomes the migration steps; release notes list it first. A major version.feat(api)!: return ISO 8601 dates
docs: deps:No type of changeLeft out, or listed under Changed if you choose.docs: explain webhooks
chore: ci: build: test: style:Left outInternal. “Include chores” keeps them.chore: tidy scripts
Other types (wip:, ops:…)By first word, else ChangedRead like a plain subject. A standard type says more.wip: onboarding flow
No type, starts with Add, Introduce, Support…AddedPlain subjects are sorted by their first word.Add CSV export
Starts with Fix, Resolve, Prevent…FixedFix the login redirect
Starts with Remove, Drop, Delete…RemovedRemove the legacy exporter
Starts with Deprecate…DeprecatedDeprecate the v1 client
Anything else (Update, Improve, Rename…)ChangedUpdate the pricing page copy
Merge commits and release commitsLeft outBookkeeping, not changes.Merge branch 'main' into feature

Types are matched without regard to case. Under Semantic Versioning, feat means a minor release, fix a patch, and any breaking change a major one. More on writing commits that make good notes in release notes from Conventional Commits.

Common mistakes

What goes wrong, and the fix.

The tool catches some of these for you. The rest are habits worth changing.

Pasting the whole history

Without a range, every old release ends up in this one. Give git the range since the last tag, or add --decorate so tags show and the tool can stop at the previous release by itself. Piped output (to pbcopy, a file) drops tags unless you pass --decorate.

git log --oneline

git log v1.4.0..HEAD --oneline --decorate

Using --oneline with BREAKING CHANGE: footers

A BREAKING CHANGE: footer is in the commit body, and one-line output only has the subject. The breaking change goes unflagged and its migration steps are lost. A ! in the subject survives either way.

git log v1.4.0..HEAD --oneline

git log v1.4.0..HEAD --no-merges

Almost-Conventional Commits

The type is followed by an optional (scope), an optional !, a colon and a space, in that order. Near misses are read as plain subjects and sorted by their first word; the tool tells you which ones.

feat:add export · feat!(api): … · feat(api) add export

feat: add export · feat(api)!: … · feat(api): add export

Hiding real changes as chore:

chore, ci, build, test and style are left out of a changelog because they're internal. If users notice the change, give it the type that says so: feat, fix, perf.

chore: speed up cold starts

perf: speed up cold starts

Subjects nobody can act on

Each subject becomes a line in the changelog. Say what changed for the person upgrading, not what you did in the code.

fix: bug · updates · wip

fix: keep query strings when following redirects

Squash merges with free-form titles

When you squash-merge, the pull request title becomes the commit. Check titles against the convention in review, or with a CI check such as commitlint.

Some fixes (#118)

fix(cli): show a clear error when the config is missing (#118)

No tags in a CI checkout

CI often clones with a shallow history and no tags, so git describe has nothing to find. Fetch them first, or set fetch-depth: 0 on actions/checkout.

fatal: No names found, cannot describe anything.

git fetch --tags --unshallow

Shipping the draft unedited

Keep a Changelog 2.0.0 is clear that a list of commits isn't a changelog. The sorting and breaking-change flags are done for you; the wording is yours to finish.

Paste, commit, tag

Paste, merge related lines, drop internal ones, add upgrade steps, then tag

From scripts and agents

The same changelog, one command away.

A free endpoint and MCP tool with the same rules as this page. No key, no account.

  • Pipe git log to itPlain text in, a Keep a Changelog section or release notes out.
  • Agents ask directlyCoding agents connected to the LogPulse MCP server call commits_to_changelog after they ship.
  • Nothing keptDeterministic, no AI, nothing stored. 30 calls a minute per IP address.
Since the last tag, as a changelog section
git log "$(git describe --tags --abbrev=0)..HEAD" --no-merges \
  | curl -s -X POST "https://release-ripple-roadmap.lovable.app/api/public/v1/commits-to-changelog?format=markdown&version=1.5.0" \
      -H "Content-Type: text/plain" --data-binary @-
Release notes instead
# same command, with
# ?format=notes
# or ?format=json for the
# sections, breaking changes
# and every commit's verdict
Claude Code
claude mcp add --transport http logpulse https://release-ripple-roadmap.lovable.app/mcp

# then ask:
# "Write the changelog for
#  everything since the last tag"

Endpoint: POST https://release-ripple-roadmap.lovable.app/api/public/v1/commits-to-changelog · a raw text/plain body or JSON { log | commits[] }. Read the docs.

Questions

Changelogs from git commits