Ingegneria

Semantic versioning e il tuo changelog

5 min di lettura

Il semantic versioning dice a chi chiama quanto può fargli male una release prima di leggere una singola voce del changelog. Passare da 2.4.1 a 2.5.0 dice: nuova capacità, niente si rompe. Passare da 2.5.0 a 3.0.0 dice: leggi questa voce prima di aggiornare. Changelog e numero di versione dovrebbero affermare la stessa cosa in due formati, e la maggior parte degli attriti tra i due emerge proprio quando non concordano, il che succede più spesso di quanto la specifica suggerirebbe.

Cosa promette davvero ogni numero in una versione?

Il semantic versioning definisce tre numeri, MAJOR.MINOR.PATCH, ognuno con una regola rigida su cosa lo attiva. Un salto MAJOR significa un cambiamento incompatibile: qualcosa che un’integrazione corretta ed esistente potrebbe notare e per cui dovrebbe cambiare. Un salto MINOR significa nuova funzionalità compatibile all’indietro: niente di esistente si rompe, qualcosa di nuovo è disponibile. Un salto PATCH significa un fix compatibile all’indietro: il comportamento si avvicina a quanto documentato, e chi contava intenzionalmente sul vecchio comportamento non dovrebbe notare nulla.

SaltoSignificatoLa voce dovrebbe leggersi come
MAJOR (1.x.x -> 2.0.0)Un cambiamento incompatibile“Serve agire prima di aggiornare”
MINOR (1.2.x -> 1.3.0)Nuova capacità compatibile“Disponibile da ora, nient’altro cambia”
PATCH (1.2.3 -> 1.2.4)Un fix compatibile“Ora si comporta come documentato”

La tabella è anche un test da eseguire al contrario: se una voce non si legge come la sua riga, o il numero di versione è sbagliato, o la voce sta sotto o sovra vendendo cosa è realmente successo.

Cosa conta come cambiamento incompatibile ai fini del versionamento?

Lo stesso test che decide se qualcosa appartiene a un changelog di API: se una chiamata corretta, scritta contro il vecchio comportamento e mai toccata da allora, potrebbe comportarsi in modo diverso a causa di questo cambiamento. Cos’è un cambiamento incompatibile, e come rilasciarlo copre la decisione per intero, inclusi i casi che sembrano incompatibili e non lo sono, e quelli che sembrano piccoli e non lo sono. In breve ai fini del versionamento: se la risposta è sì, il salto è MAJOR indipendentemente da quanto codice il cambiamento abbia toccato internamente. I numeri di versione seguono la conseguenza per chi chiama, non lo sforzo del team.

Come dovrebbe corrispondere una voce di changelog a un salto di versione?

Una voce, una categoria di salto, dichiarata subito. Il pattern della tabella continua direttamente: una voce incompatibile sta sotto la versione che l’ha introdotta, formulata prima come avviso e poi come descrizione. Una voce additiva sta sotto la sua versione MINOR, formulata come disponibilità. Un fix sta sotto la sua versione PATCH, formulato come correzione. Mescolare categorie in una voce, come infilare un cambiamento incompatibile nello stesso paragrafo di un fix non correlato, è il modo in cui chi legge perde proprio l’unica cosa che contava davvero.

## 3.0.0 (2026-09-07)

### Changed
- **BREAKING:** `GET /reports` ora restituisce gli importi come interi
  nell'unità monetaria più piccola (centesimi) invece che come
  decimali. Aggiorna il codice che legge `amount` direttamente.

## 2.9.0 (2026-09-01)

### Added
- I report ora si possono filtrare per `status`.

## 2.8.4 (2026-08-28)

### Fixed
- `GET /reports?status=` restituiva una pagina vuota invece di un 400
  per uno stato sconosciuto.

Letto dall’alto in basso, il numero di versione e l’etichetta di sezione dicono la stessa cosa due volte, ed è esattamente lo scopo: chi legge solo i titoli ottiene una lettura corretta del rischio prima di aprire una sola riga.

La regola dei cambiamenti incompatibili si applica allo stesso modo prima della 1.0.0?

No, ed è qui che nasce la maggior parte della confusione su “era davvero incompatibile”. SemVer è esplicito nel dire che la versione maggiore zero, 0.y.z, serve allo sviluppo iniziale: qualsiasi cosa può cambiare in qualsiasi momento, e l’API pubblica non dovrebbe essere considerata stabile. Un salto da 0.4.0 a 0.5.0 può portare un cambiamento incompatibile senza violare la specifica, perché la garanzia sulla versione maggiore parte solo una volta che un progetto pubblica 1.0.0. Una voce di changelog deve comunque a chi legge la stessa onestà su cosa si è rotto; ciò che cambia è solo che il numero di versione in sé non è il segnale su cui affidarsi prima che arrivi la 1.0.0.

E se il tuo prodotto non rilascia versioni discrete?

La maggior parte dei prodotti SaaS distribuisce in continuo e non mostra mai un numero di versione a chi chiama, il che non elimina il bisogno di questa disciplina, solo il numero che normalmente la porterebbe. La voce di changelog deve fare tutto il lavoro da sola: dire chiaramente se un cambiamento è incompatibile, additivo o un fix, con le stesse tre parole che usa il semantic versioning, anche senza un campo versione a cui agganciarle. Alcuni team mantengono una versione puramente interna solo per ancorare le voci di changelog a qualcosa di collegabile, senza mai mostrarla direttamente a chi chiama.

Come si applica questo specificamente a un changelog di API?

In modo più rigido che quasi ovunque altrove, perché chi chiama un’API è codice, non persone che possono scrollare le spalle davanti a un cambiamento inaspettato. Changelog di API: cosa pubblicare e chi lo legge copre la forma completa di quel documento; la disciplina di versionamento qui è ciò che mantiene oneste le sue sezioni breaking e additive. Un’API che offre più versioni contemporaneamente, come v1 e v2 servite in parallelo durante una finestra di migrazione, sta di fatto applicando il semantic versioning alla scala dell’intera interfaccia invece di un singolo pacchetto, e lo stesso vocabolario di tre parole si applica ancora a ogni voce.

Cosa dice Keep a Changelog sul versionamento?

Si lega direttamente per nome al semantic versioning e raccomanda lo stesso vocabolario di categorie usato in questo articolo: Added, Changed, Deprecated, Removed, Fixed, Security. Keep a Changelog, in pratica percorre come adottare quella specifica, inclusi i punti in cui i team tendono a deviare. La sovrapposizione non è un caso: entrambe le specifiche cercano di risolvere lo stesso problema da estremi opposti, una standardizza il numero di versione e l’altra la voce che lo spiega.

FAQ

Ogni voce di changelog ha bisogno di un numero di versione? Se il prodotto rilascia versioni, sì, perché il numero permette a chi legge di saltare direttamente a “quanto mi riguarda” senza leggere prima la voce. Se il prodotto distribuisce in continuo senza campo versione, la formulazione della voce deve portare da sola quel segnale.

Qual è la differenza tra un salto MAJOR e una voce di cambiamento incompatibile? Dovrebbero essere lo stesso evento descritto in due modi. Il numero di versione è il segnale leggibile dalla macchina (gli strumenti di chi chiama possono reagirvi); la voce di changelog è la spiegazione leggibile dall’uomo di cosa è cambiato concretamente.

Una release PATCH può essere incompatibile? Per definizione non dovrebbe. Se ne è uscita una comunque, non modificate né ritaggate la versione pubblicata: la FAQ di SemVer dice di rilasciare una nuova versione che ripristini la compatibilità, o una nuova MAJOR se l’incompatibilità resta, e di documentare la versione incriminata così che gli utenti sappiano di saltarla.

I cambiamenti puramente interni hanno bisogno di un salto di versione? No. Il semantic versioning segue l’interfaccia pubblica. Un refactoring senza effetto osservabile per chi chiama non ha bisogno né di un salto né di una voce di changelog, anche se è stato un lavoro di ingegneria significativo.


Le affermazioni tecniche di questo articolo non sono state verificate in modo indipendente. Se qualcosa non è corretto, faccelo sapere e lo correggeremo.

Correlati su changeloop: Generatore di changelog, Documentazione per sviluppatori

changeloop
Il team che costruisce un changelog che chiude il cerchio. I tuoi utenti chiedono, il tuo team rilascia, chi ha chiesto lo viene a sapere.