Engineering

CHANGELOG.md: was hinein gehört und wie sie aktuell bleibt

5 Min. Lesezeit

Eine CHANGELOG.md ist eine Markdown-Datei im Wurzelverzeichnis eines Repositorys, die für jede veröffentlichte Version auflistet, was sich geändert hat, in Worten, mit denen eine Nutzerin des Projekts etwas anfangen kann. Die Datei lesen Leute, die entscheiden, ob sie upgraden, Leute, die nach einem Upgrade debuggen, und Paket-Registries und Release-Werkzeuge, die sie auf der Projektseite darstellen. Das Format, dem die meisten Projekte folgen, ist das von keepachangelog.com: neueste Version oben, darüber ein Abschnitt Unreleased, und Einträge gruppiert unter Added, Changed, Deprecated, Removed, Fixed und Security.

RubrikWas hinein gehörtBeispielzeile
UnreleasedGemergte Änderungen, die noch in keiner Version sind- Export now streams, so files over 100 MB no longer time out.
AddedNeue Fähigkeit, die eine Nutzerin erreichen kann- \—dry-run` flag on `deploy` prints the plan without applying it.`
ChangedBestehendes Verhalten, das jetzt anders funktioniert- Default timeout raised from 30 s to 60 s.
DeprecatedFunktioniert noch, Entfernung geplant- \legacyAuth()` will be removed in 3.0; use `auth()`.`
RemovedIn dieser Version weg- Dropped Node 16 support.
FixedEin Bug, auf den eine Nutzerin hätte stoßen können- Search no longer fails on queries containing a hyphen.
SecurityFixes, für die eine Leserin heute upgraden sollte- Fixed a path traversal in the static file handler (CVE pending).

Was ist eine CHANGELOG.md-Datei?

Sie ist die menschenlesbare Geschichte eines Projekts, eine Version nach der anderen, neben dem Code aufbewahrt, damit sie mit ihm ausgeliefert wird. Von git log unterscheidet sie sich in Zielgruppe und Auswahl: Das Git-Log hält jeden Commit für die Leute fest, die ihn geschrieben haben, der Changelog die Änderungen, die eine Nutzerin bemerken würde, geschrieben für die Person, die sie nicht geschrieben hat. Ein Commit, der eine interne Variable umbenennt, hat keine Changelog-Zeile. Ein Commit, der einen Standard-Timeout ändert, hat eine, auch wenn der Diff ein einziges Zeichen war.

Die Datei liegt unter genau diesem Namen im Wurzelverzeichnis des Repositorys, weil Werkzeuge sie dort suchen. GitHub verlinkt sie von der Repository-Seite, npm und PyPI stellen sie dar, wenn sie im Paket enthalten ist, und Release-Werkzeuge wie release-please und semantic-release lesen und schreiben sie an Ort und Stelle. Kleingeschriebenes changelog.md und CHANGES.md funktionieren für Menschen ebenfalls, aber manche Werkzeuge suchen nur nach dem kanonischen Namen.

Wie sieht eine vollständige CHANGELOG.md aus?

Ein kurzes, korrektes Beispiel ist mehr wert als eine lange Beschreibung. Dieses folgt dem Aufbau von Keep a Changelog 1.1.0 und Semantic Versioning für die Nummern.

# Changelog

All notable changes to this project are listed here.
Format: Keep a Changelog. Versions: Semantic Versioning.

## [Unreleased]

### Added
- `--dry-run` flag on `deploy` prints the plan without applying it.

## [2.3.1] - 2026-10-01

### Fixed
- Search no longer fails on queries containing a hyphen. Broken
  since 2.3.0.

### Security
- Fixed a path traversal in the static file handler. Upgrade today
  if you serve user-uploaded files.

## [2.3.0] - 2026-09-18

### Added
- Streaming export. Files over 100 MB no longer time out.

### Deprecated
- `legacyAuth()` still works but will be removed in 3.0.
  Use `auth()`.

[Unreleased]: https://github.com/acme/tool/compare/v2.3.1...HEAD
[2.3.1]: https://github.com/acme/tool/compare/v2.3.0...v2.3.1
[2.3.0]: https://github.com/acme/tool/compare/v2.2.0...v2.3.0

Vier Details tragen den größten Teil des Werts. Jede Version hat ein Datum im ISO-Format, sodass eine Leserin es mit dem Zeitpunkt abgleichen kann, an dem ihr Problem anfing. Jede Versionsüberschrift ist ein Link auf die Compare-Ansicht, der volle Diff ist also einen Klick entfernt. Ein Fix sagt, welche Version es kaputt gemacht hat. Und die Rubrik Security steht für sich, sodass jemand, der nach “muss ich jetzt upgraden” sucht, sie in Sekunden findet.

Wie hält man eine CHANGELOG.md aktuell?

Schreibt die Zeile im selben Pull Request wie die Änderung, unter Unreleased, und verschiebt den Abschnitt beim Release unter eine Versionsüberschrift. Das ist die ganze Methode. Die Datei veraltet, wenn die Zeile später von jemand anderem geschrieben wird, zum Release-Zeitpunkt, aus einer Liste von Commit-Nachrichten, die diese Person nicht verfasst hat.

Zwei Dinge lassen die Gewohnheit halten. Das erste ist ein Check in CI, der einen Pull Request scheitern lässt, der src/ anfasst, ohne den Changelog anzufassen, mit einem Label zum Überspringen für Änderungen ohne sichtbare Wirkung; ein Changelog-Check als GitHub Action zeigt die Vierzig-Zeilen-Version. Das zweite ist ein Release-Schritt, der Unreleased mit einem Befehl in Version und Datum umbenennt, damit niemand daran denken muss, es von Hand zu tun. Wer schreibt den Changelog behandelt, wie Teams die Frage klären, wessen Aufgabe die Zeile ist.

Sollte der Changelog aus Commits generiert werden?

Generieren liefert euch einen vollständigen Entwurf; es liefert euch keinen Changelog. Werkzeuge auf Basis von Conventional Commits und Release-Automatisierung wie release-please lesen die Präfixe feat:, fix: und BREAKING CHANGE: und erzeugen eine gruppierte Liste, in der jeder Pull Request verlinkt ist. Die Liste ist nur so gut wie die Commit-Betreffzeilen, und Commit-Betreffzeilen beschreiben den Code.

Der gangbare Mittelweg ist: generieren, dann überarbeiten. Lasst das Werkzeug den Abschnitt Unreleased aus Commits erzeugen, und lasst den Release-Pull-Request die Zeilen umschreiben, die eine Nutzerin lesen würde: das Symptom statt des Funktionsnamens, die Einstellung, die umgezogen ist, statt der Datei, die sich geändert hat. Von Conventional Commits zum Changelog geht die Pipeline durch, und ein Changelog-Generator im Browser reicht, um aus einem eingefügten git log einen Entwurf zu bekommen, ohne etwas zu installieren.

Was gehört nicht in die CHANGELOG.md?

Interne Refactorings, Abhängigkeits-Updates ohne Verhaltensänderung, reine Test-Commits, CI-Konfiguration und Formatierungsänderungen. Sie gehören in die Git-Historie, wo jede, die sie braucht, sie finden kann. Sie aufzunehmen vergräbt die Zeilen, die zählen, und bringt Leserinnen bei, die Datei zu überspringen.

Das andere, was draußen bleibt, ist die Marketing-Fassung einer Änderung. “Blitzschnelle Exporte” sagt einer Leserin nichts, was sie prüfen könnte. “Export streamt jetzt; Dateien über 100 MB laufen nicht mehr in einen Timeout” schon. Die Datei ist ein Nachschlagedokument, und ihr Ton sollte dazu passen: kurze Zeilen, konkrete Substantive, eine Version oder ein Datum an allem. Keep a Changelog, umgesetzt behandelt die Teile der Spezifikation, die Teams am häufigsten weglassen, und Changelog-Dateiformate, wann eine JSON- oder YAML-Quelle neben der Markdown-Datei ihren Aufwand wert ist.

Braucht ein Produkt mit Changelog-Seite die Datei trotzdem?

Eine Bibliothek ja, weil die Datei das ist, was Paket-Registries darstellen und was eine Entwicklerin offline liest. Ein SaaS-Produkt ohne installierbares Artefakt kommt mit der Seite allein aus, denn seine Nutzerinnen sehen das Repository nie. Viele Teams fahren beides: die Datei als technische Aufzeichnung und eine öffentliche Changelog-Seite, die daraus für ein breiteres Publikum geschrieben wird, mit der Detailaufteilung, die Changelog vs. Release Notes beschreibt. Wird die Seite aus der Datei gespeist, bleibt die Datei die Quelle der Wahrheit und die Seite wird generiert, damit es einen Ort zum Bearbeiten gibt.

FAQ

Was ist der Unterschied zwischen CHANGELOG.md und Release Notes? Der Changelog ist die vollständige, laufende Aufzeichnung jeder nennenswerten Änderung, im Repository aufbewahrt. Release Notes sind eine Nachricht zu einem Release, oft kürzer und für ein breiteres Publikum neu geschrieben. Viele Projekte veröffentlichen den Changelog-Abschnitt einer Version als ihre Release Notes.

Wo sollte die CHANGELOG.md liegen? Im Wurzelverzeichnis des Repositorys, unter genau diesem Namen, damit GitHub, Paket-Registries und Release-Werkzeuge sie finden. Ein Monorepo hält eine pro Paket, neben dem jeweiligen Manifest des Pakets.

Sollte ich die CHANGELOG.md aus Git-Commits generieren? Generiert den Entwurf, dann überarbeitet die Zeilen, die eine Nutzerin lesen wird. Commit-Nachrichten beschreiben die Code-Änderung; der Changelog beschreibt, was eine Nutzerin bemerkt. Werkzeuge wie conventional-changelog und release-please liefern einen guten Ausgangspunkt.

Braucht jeder Commit einen Changelog-Eintrag? Nein. Nur Änderungen, die eine Nutzerin des Projekts bemerken könnte: neue Fähigkeiten, geändertes Verhalten, Abkündigungen, Entfernungen, Fixes und Sicherheits-Patches. Refactorings, Test-Änderungen und CI-Anpassungen bleiben in der Git-Historie.


Die technischen Aussagen in diesem Artikel wurden nicht unabhängig geprüft. Wenn etwas nicht stimmt, sagen Sie es uns, und wir korrigieren es.

Mehr bei changeloop: Changelog-Generator, Changelog-Beispiele

changeloop
Das Team hinter einem Changelog, das den Kreis schließt. Ihre Nutzer fragen, Ihr Team liefert, und wer gefragt hat, erfährt davon.