Skip to content

Generated output format

GenerateFromRepo returns a markdown string. This is exactly what it contains — no template, no configuration, no way to change any of it short of post-processing the string yourself.

The shape of one release

# v1.2.0

### Features

* **cli:** add a --json flag
* add the greeting command

### Bug Fixes

* **http:** retry on 503
  • Release heading: # (level 1), holding the tag name exactly as it appears in the repository. A tag named 1.0.0 produces # 1.0.0; the v is not added.
  • Category heading: ### (level 3). There is no level-2 heading anywhere in the output.
  • Entries: * bullets. With a scope, * **scope:** description. Without one, * description.
  • Blank lines: one after the release heading, one after each category heading, and one between releases. The string ends with a newline after the last bullet.

Order of everything

  1. Unreleased first, if any commit is not reachable from a tag. The literal string Unreleased is used as the version.
  2. Tagged releases, newest first, ordered by semver — so v1.10.0 precedes v1.9.0, whatever order the tags were created in.
  3. Categories within a release, always in this order, with empty ones omitted: Breaking Changes → Features → Bug Fixes → Performance Improvements → Other.
  4. Entries within a category, newest commit first by committer time.

What is not in the output

No commit hashes, dates, authors, links, compare URLs, issue references or contributor lists. No document title — there is no leading # Changelog heading, so the first line of the string is the first release heading. No footnotes and no front matter.

The output is deliberately the same information a Changelog value holds, which is why it round-trips through Parse. Anything richer would be information the parser cannot read back.

The empty and near-empty cases

Situation Output
Repository with no commits "" — empty string, nil error
Repository whose every commit was dropped (all test/ci, or all unrecognised) "", nil error
Commits but no tags A single # Unreleased section
A release whose commits were all dropped The release is omitted entirely — no heading
Two tags on the same commit The lower semver keeps the entries; the higher is emitted as a heading with no body

That last pair is worth reading twice. A tag whose commits were all test/ci disappears from the changelog without trace, while a tag that collided with another on the same commit gets an empty section. Both are deliberate; neither is configurable.

Writing the output somewhere

GenerateFromRepo returns a string and nothing else. It does not write a file, does not know the name CHANGELOG.md, and does not merge with an existing changelog — if you regenerate, you are producing the whole document again from history, and it is your program's job to decide what to do with it.