Semantic versioning și changelog-ul tău
5 min de citit
Semantic versioning îi spune celei care apelează cât de mult poate durea o lansare înainte să
citească o singură intrare din changelog. Trecerea de la 2.4.1 la 2.5.0 spune: capacitate
nouă, nimic nu se strică. Trecerea de la 2.5.0 la 3.0.0 spune: citește această intrare
înainte de actualizare. Changelog-ul și numărul de versiune ar trebui să afirme același lucru în
două formate, iar cea mai mare parte a frecării dintre ele apare exact când nu se potrivesc, ceea
ce se întâmplă mai des decât ar sugera specificația.
Ce promite de fapt fiecare cifră dintr-o versiune?
Semantic versioning definește trei cifre, MAJOR.MINOR.PATCH, fiecare cu
o regulă strictă despre ce o declanșează. Un salt MAJOR înseamnă o schimbare incompatibilă: ceva
ce o integrare corectă și existentă ar putea observa și pentru care ar trebui să se schimbe. Un
salt MINOR înseamnă funcționalitate nouă, compatibilă retroactiv: nimic existent nu se strică,
ceva nou devine disponibil. Un salt PATCH înseamnă o remediere compatibilă retroactiv:
comportamentul se apropie de ce era documentat, și nimeni care s-a bazat intenționat pe
comportamentul vechi nu ar trebui să observe ceva.
| Salt | Semnificație | Intrarea ar trebui să sune ca |
|---|---|---|
MAJOR (1.x.x -> 2.0.0) | O schimbare incompatibilă | “Necesită acțiune înainte de actualizare” |
MINOR (1.2.x -> 1.3.0) | Capacitate nouă, compatibilă | “Disponibilă de acum, nimic altceva nu s-a schimbat” |
PATCH (1.2.3 -> 1.2.4) | O remediere compatibilă | “Se comportă acum așa cum era documentat” |
Tabelul e și un test invers: dacă o intrare nu se citește ca rândul ei, fie numărul de versiune e greșit, fie intrarea subvinde sau supravinde ce s-a întâmplat de fapt.
Ce contează ca incompatibil în scopuri de versionare?
Același test care decide dacă ceva aparține unui changelog de API: dacă o apelantă corectă, scrisă împotriva comportamentului vechi și neatinsă de atunci, s-ar putea comporta diferit din cauza acestei schimbări. Ce e o schimbare incompatibilă, și cum o lansezi acoperă decizia integral, inclusiv cazurile care par incompatibile și nu sunt, și cele care par mici și nu sunt. Pe scurt pentru versionare: dacă răspunsul e da, saltul e MAJOR indiferent cât cod a atins schimbarea de fapt intern. Numerele de versiune urmăresc consecința pentru apelantă, nu efortul echipei.
Cum ar trebui să se potrivească o intrare de changelog cu un salt de versiune?
O intrare, o categorie de salt, spusă chiar de la început. Modelul din tabel continuă direct: o intrare incompatibilă stă sub versiunea care a introdus-o, formulată întâi ca avertisment apoi ca descriere. O intrare adițională stă sub versiunea ei MINOR, formulată ca disponibilitate. O remediere stă sub versiunea ei PATCH, formulată ca o corecție. Amestecarea categoriilor într-o intrare, cum ar fi îndoirea unei schimbări incompatibile în același paragraf cu o remediere nelegată, e felul în care o cititoare ratează exact singurul lucru care conta cu adevărat.
## 3.0.0 (2026-09-07)
### Changed
- **BREAKING:** `GET /reports` returnează acum sumele ca numere
întregi în cea mai mică unitate monetară (bani) în loc de zecimale.
Actualizează codul care citește `amount` direct.
## 2.9.0 (2026-09-01)
### Added
- Rapoartele pot fi acum filtrate după `status`.
## 2.8.4 (2026-08-28)
### Fixed
- `GET /reports?status=` returna o pagină goală în loc de 400 pentru
un status necunoscut.
Citit de sus în jos, numărul de versiune și eticheta de secțiune spun același lucru de două ori, și exact acesta e scopul: o cititoare care doar parcurge titlurile primește o citire corectă a riscului înainte să deschidă o singură linie.
Se aplică regula schimbării incompatibile la fel înainte de 1.0.0?
Nu, și de aici vine cea mai mare parte a confuziei despre “chiar a fost incompatibilă aia”. SemVer
e explicit că versiunea majoră zero, 0.y.z, e pentru dezvoltare inițială: orice se poate schimba
oricând, iar API-ul public nu ar trebui considerat stabil. Un salt de la 0.4.0 la 0.5.0 poate
purta o schimbare incompatibilă fără să încalce specificația, pentru că garanția versiunii majore
începe abia odată ce un proiect lansează 1.0.0. O intrare de changelog tot datorează cititoarelor
aceeași onestitate despre ce s-a stricat; ce se schimbă e doar că numărul de versiune în sine nu e
semnalul pe care să te bazezi înainte să sosească 1.0.0.
Dacă produsul tău nu lansează versiuni discrete?
Majoritatea produselor SaaS se implementează continuu și nu arată niciodată un număr de versiune apelantei, ceea ce nu elimină nevoia acestei discipline, doar cifra care ar purta-o în mod normal. Intrarea de changelog trebuie să facă toată munca singură: să spună clar dacă o schimbare e incompatibilă, adițională, sau o remediere, cu aceleași trei cuvinte pe care le folosește semantic versioning, chiar și fără un câmp de versiune de care să le agațe. Unele echipe păstrează o versiune pur internă doar ca să ancoreze intrările de changelog la ceva ce poate fi linkuit, fără s-o arate vreodată direct apelantei.
Cum se aplică asta specific unui changelog de API?
Mai strict decât aproape oriunde altundeva, pentru că apelantele unui API sunt cod, nu oameni
care pot da din umeri la o schimbare neașteptată. Changelog de API: ce publici și cine îl citește
acoperă forma completă a acelui document; disciplina de versionare de aici e ceea ce menține
oneste secțiunile lui breaking și adiționale. Un API care oferă mai multe versiuni simultan, cum
ar fi v1 și v2 servite în paralel în timpul unei ferestre de migrare, aplică efectiv semantic
versioning la scara întregii interfețe în loc de un singur pachet, iar același vocabular de trei
cuvinte se aplică în continuare fiecărei intrări.
Ce spune Keep a Changelog despre versionare?
Se leagă direct prin nume de semantic versioning și recomandă același vocabular de categorii pe care îl folosește acest articol: Added, Changed, Deprecated, Removed, Fixed, Security. Keep a Changelog, în practică parcurge cum se adoptă acea specificație, inclusiv unde echipele tind să se abată de la ea. Suprapunerea nu e o coincidență: ambele specificații încearcă să rezolve aceeași problemă din capete opuse, una standardizează numărul de versiune iar cealaltă intrarea care îl explică.
FAQ
Are nevoie fiecare intrare de changelog de un număr de versiune? Dacă produsul lansează versiuni, da, pentru că cifra permite unei cititoare să sară direct la “cât de mult mă afectează asta” fără să citească întâi intrarea. Dacă produsul se implementează continuu fără câmp de versiune, formularea intrării trebuie să poarte singură acel semnal.
Care e diferența dintre un salt MAJOR și o intrare de schimbare incompatibilă? Ar trebui să descrie același eveniment în două moduri. Numărul de versiune e semnalul citibil de mașină (uneltele apelantei pot reacționa la el); intrarea de changelog e explicația citibilă de om a ceea ce s-a schimbat concret.
Poate fi o lansare PATCH incompatibilă? Prin definiție nu ar trebui. Dacă totuși a fost lansat unul, nu edita și nu re-eticheta versiunea publicată: FAQ-ul SemVer spune să lansezi o versiune nouă care restabilește compatibilitatea, sau o nouă versiune MAJOR dacă incompatibilitatea rămâne, și să documentezi versiunea problematică, ca utilizatorii să știe să o sară.
Au nevoie schimbările pur interne de un salt de versiune? Nu. Semantic versioning urmărește interfața publică. O refactorizare fără efect observabil pentru apelantă nu are nevoie nici de salt, nici de intrare de changelog, chiar dacă a fost o muncă de inginerie semnificativă intern.
Afirmațiile tehnice din acest articol nu au fost verificate independent. Dacă ceva nu e corect, spune-ne și vom corecta.