Inginerie

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.

SaltSemnificațieIntrarea 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.

Pe changeloop: Generator de changelog, Documentație pentru dezvoltatori

changeloop
Echipa care construiește un changelog care închide bucla. Utilizatorii cer ceva, echipa ta livrează, cel care a cerut află.