Semantic versioning en je changelog
5 min lezen
Semantic versioning vertelt een aanroeper hoeveel pijn een release kan doen voordat ze één
changelog-regel hebben gelezen. Van 2.4.1 naar 2.5.0 zegt: nieuwe capaciteit, niets breekt.
Van 2.5.0 naar 3.0.0 zegt: lees deze regel voor je update. Changelog en versienummer horen
hetzelfde te beweren in twee formaten, en de meeste wrijving tussen de twee duikt precies op
wanneer ze het oneens zijn, wat vaker gebeurt dan de specificatie zou suggereren.
Wat belooft elk cijfer in een versie eigenlijk?
Semantic versioning definieert drie cijfers, MAJOR.MINOR.PATCH, elk met
een strikte regel over wat het triggert. Een MAJOR-sprong betekent een breaking change: iets wat
een correcte, bestaande integratie zou kunnen opmerken en waarvoor ze zouden moeten veranderen.
Een MINOR-sprong betekent nieuwe, achterwaarts compatibele functionaliteit: niets bestaands
breekt, iets nieuws is beschikbaar. Een PATCH-sprong betekent een achterwaarts compatibele fix:
gedrag komt dichter bij wat gedocumenteerd was, en niemand die opzettelijk vertrouwde op het oude
gedrag zou iets moeten merken.
| Sprong | Betekenis | Regel hoort te lezen als |
|---|---|---|
MAJOR (1.x.x -> 2.0.0) | Een breaking change | “Actie nodig voor je update” |
MINOR (1.2.x -> 1.3.0) | Nieuwe, compatibele capaciteit | “Nu beschikbaar, verder niets veranderd” |
PATCH (1.2.3 -> 1.2.4) | Een compatibele fix | “Gedraagt zich nu zoals gedocumenteerd” |
De tabel is ook een test die achterstevoren werkt: als een regel niet leest als zijn rij, klopt of het versienummer niet, of verkoopt de regel wat er echt gebeurde te klein of te groot.
Wat telt als breaking voor versioneringsdoeleinden?
Dezelfde test die bepaalt of iets thuishoort in een API-changelog: of een correcte aanroeper, geschreven tegen het oude gedrag en sindsdien onaangeraakt, zich anders zou kunnen gedragen door deze verandering. Wat is een breaking change, en hoe breng je die uit behandelt de beslissing volledig, inclusief gevallen die breaking lijken en dat niet zijn, en die klein lijken en dat niet zijn. Kort voor versioneringsdoeleinden: als het antwoord ja is, is de sprong MAJOR ongeacht hoeveel code de verandering intern echt raakte. Versienummers volgen het gevolg voor de aanroeper, niet de inspanning van het team.
Hoe moet een changelog-regel overeenkomen met een versiesprong?
Eén regel, één sprongcategorie, meteen vooraan genoemd. Het patroon uit de tabel zet zich direct voort: een breaking regel staat onder de versie die het introduceerde, eerst geformuleerd als waarschuwing en dan als beschrijving. Een additieve regel staat onder zijn MINOR-versie, geformuleerd als beschikbaarheid. Een fix staat onder zijn PATCH-versie, geformuleerd als correctie. Categorieën mengen in één regel, zoals een breaking change in dezelfde alinea vouwen als een ongerelateerde fix, is hoe een lezer precies het ene mist dat er echt toe deed.
## 3.0.0 (2026-09-07)
### Changed
- **BREAKING:** `GET /reports` geeft bedragen nu terug als gehele
getallen in de kleinste valuta-eenheid (centen) in plaats van
decimalen. Werk code bij die `amount` rechtstreeks leest.
## 2.9.0 (2026-09-01)
### Added
- Rapporten kunnen nu gefilterd worden op `status`.
## 2.8.4 (2026-08-28)
### Fixed
- `GET /reports?status=` gaf een lege pagina terug in plaats van een
400 voor een onbekende status.
Van boven naar beneden gelezen zeggen versienummer en sectielabel hetzelfde twee keer, en dat is precies het doel: een lezer die alleen de koppen scant, krijgt een correcte risico-inschatting voordat ze ook maar één regel openen.
Geldt de breaking-change-regel op dezelfde manier vóór 1.0.0?
Nee, en dat is waar het meeste van de verwarring over “was dat nu echt breaking” vandaan komt.
SemVer is expliciet dat hoofdversie nul, 0.y.z, bedoeld is voor initiële ontwikkeling: alles mag
op elk moment veranderen, en de publieke API zou niet als stabiel moeten worden beschouwd. Een
sprong van 0.4.0 naar 0.5.0 kan een breaking change bevatten zonder de spec te schenden, omdat
de garantie op hoofdversie pas begint zodra een project 1.0.0 uitbrengt. Een changelog-regel is
lezers nog steeds dezelfde eerlijkheid schuldig over wat er kapot ging; wat verandert is alleen dat
het versienummer zelf niet het signaal is om op te vertrouwen voordat 1.0.0 arriveert.
Wat als je product geen discrete versies uitbrengt?
De meeste SaaS-producten deployen continu en tonen een aanroeper nooit een versienummer, wat de noodzaak van deze discipline niet wegneemt, alleen het cijfer dat het normaal zou dragen. De changelog-regel moet al het werk alleen doen: duidelijk zeggen of een verandering breaking, additief, of een fix is, met dezelfde drie woorden die semantic versioning gebruikt, ook zonder versieveld om ze aan te hangen. Sommige teams houden een puur interne versie bij, alleen om changelog-regels te verankeren aan iets linkbaars, zonder het ooit rechtstreeks aan de aanroeper te tonen.
Hoe geldt dit specifiek voor een API-changelog?
Strenger dan bijna overal elders, omdat aanroepers van een API code zijn, geen mensen die met de
schouders kunnen ophalen bij een onverwachte verandering. API-changelog: wat te publiceren en wie het leest
behandelt de volledige vorm van dat document; de versioneringsdiscipline hier houdt de breaking- en
additieve secties eerlijk. Een API die meerdere versies tegelijk aanbiedt, zoals v1 en v2
parallel bediend tijdens een migratievenster, past semantic versioning in de praktijk toe op het
niveau van de hele interface in plaats van één pakket, en hetzelfde drieledige vocabulaire geldt
nog steeds voor elke regel.
Wat zegt Keep a Changelog over versionering?
Het koppelt zich rechtstreeks bij naam aan semantic versioning en beveelt hetzelfde categorievocabulaire aan dat dit artikel gebruikt: Added, Changed, Deprecated, Removed, Fixed, Security. Keep a Changelog, in de praktijk loopt door hoe je die specificatie in de praktijk toepast, inclusief waar teams meestal afdwalen. De overlap is geen toeval: beide specificaties proberen hetzelfde probleem vanaf tegenovergestelde kanten op te lossen, de ene standaardiseert het versienummer en de andere de regel die het uitlegt.
FAQ
Heeft elke changelog-regel een versienummer nodig? Als het product versies uitbrengt, ja, omdat het cijfer een lezer toelaat direct naar “hoeveel raakt dit mij” te springen zonder de regel eerst te lezen. Als het product continu deployt zonder versieveld, moet de formulering van de regel dat signaal alleen dragen.
Wat is het verschil tussen een MAJOR-sprong en een breaking-change-regel? Ze horen hetzelfde evenement op twee manieren te beschrijven. Het versienummer is het machine-leesbare signaal (tooling van de aanroeper kan erop reageren); de changelog-regel is de mensleesbare uitleg van wat er concreet veranderde.
Kan een PATCH-release breaking zijn? Per definitie zou dat niet moeten. Is er toch een uitgebracht, bewerk of hertag de gepubliceerde versie dan niet: de SemVer-FAQ zegt een nieuwe versie uit te brengen die de compatibiliteit herstelt, of een nieuwe MAJOR als de breuk blijft, en de betreffende versie te documenteren zodat gebruikers weten dat ze die moeten overslaan.
Hebben puur interne veranderingen een versiesprong nodig? Nee. Semantic versioning volgt de publieke interface. Een refactor zonder waarneembaar effect voor een aanroeper heeft geen sprong of changelog-regel nodig, zelfs als het intern significant engineeringwerk was.
De technische beweringen in dit artikel zijn niet onafhankelijk gecontroleerd. Klopt er iets niet, laat het ons weten, dan corrigeren we het.