CHANGELOG.md: cosa contiene e come tenerlo aggiornato
6 min di lettura
Un CHANGELOG.md è un file Markdown nella radice di un repository che elenca, per ogni versione rilasciata, cosa è cambiato in termini su cui un utente del progetto può agire. Lo leggono le persone che decidono se aggiornare, le persone che fanno debug dopo un aggiornamento, e i registri di pacchetti e gli strumenti di release che lo mostrano nella pagina del progetto. Il formato che la maggior parte dei progetti segue è quello descritto su keepachangelog.com: la versione più recente in cima, una sezione Unreleased sopra di essa, e voci raggruppate sotto Added, Changed, Deprecated, Removed, Fixed e Security.
| Sezione | Cosa contiene | Riga di esempio |
|---|---|---|
Unreleased | Modifiche integrate ma non ancora in una versione | - L'export ora è in streaming, quindi i file sopra i 100 MB non vanno più in timeout. |
Added | Nuova capacità raggiungibile da un utente | - L'opzione \—dry-run` su `deploy` stampa il piano senza applicarlo.` |
Changed | Comportamento esistente che ora funziona diversamente | - Timeout predefinito portato da 30 s a 60 s. |
Deprecated | Funziona ancora, in programma per la rimozione | - \legacyAuth()` verrà rimossa nella 3.0; usa `auth()`.` |
Removed | Sparito in questa versione | - Rimosso il supporto a Node 16. |
Fixed | Un bug che un utente poteva incontrare | - La ricerca non fallisce più sulle query che contengono un trattino. |
Security | Correzioni per cui un lettore dovrebbe aggiornare oggi | - Corretto un path traversal nel gestore dei file statici (CVE in attesa). |
Cos’è un file CHANGELOG.md?
È la cronologia leggibile di un progetto, una versione alla volta, tenuta accanto al codice così da viaggiare con esso. Si distingue da git log per pubblico e selezione: il log di git registra ogni commit per le persone che l’hanno scritto, mentre il changelog registra le modifiche che un utente noterebbe, scritte per la persona che non le ha scritte. Un commit che rinomina una variabile interna non ha una riga nel changelog. Un commit che cambia un timeout predefinito ce l’ha, anche se il diff era di un solo carattere.
Il file sta nella radice del repository con esattamente quel nome perché gli strumenti lo cercano lì. GitHub lo linka dalla pagina del repository, npm e PyPI lo mostrano quando è incluso nel pacchetto, e strumenti di release come release-please e semantic-release lo leggono e lo scrivono sul posto. Anche changelog.md minuscolo e CHANGES.md funzionano per le persone, ma alcuni strumenti cercano solo il nome canonico.
Che aspetto ha un CHANGELOG.md completo?
Un esempio breve e corretto vale più di una lunga descrizione. Questo segue la struttura di Keep a Changelog 1.1.0 e il versionamento semantico per i numeri.
# Changelog
Tutte le modifiche rilevanti a questo progetto sono elencate qui.
Formato: Keep a Changelog. Versioni: Semantic Versioning.
## [Unreleased]
### Added
- L'opzione `--dry-run` su `deploy` stampa il piano senza applicarlo.
## [2.3.1] - 2026-10-01
### Fixed
- La ricerca non fallisce più sulle query che contengono un
trattino. Rotta dalla 2.3.0.
### Security
- Corretto un path traversal nel gestore dei file statici.
Aggiorna oggi se servi file caricati dagli utenti.
## [2.3.0] - 2026-09-18
### Added
- Export in streaming. I file sopra i 100 MB non vanno più in
timeout.
### Deprecated
- `legacyAuth()` funziona ancora ma verrà rimossa nella 3.0.
Usa `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
Quattro dettagli portano la maggior parte del valore. Ogni versione ha una data in formato ISO, così un lettore può confrontarla con il momento in cui è iniziato il suo problema. Ogni titolo di versione è un link alla vista di confronto, così il diff completo è a un clic. Una correzione dice quale versione aveva rotto la cosa. E la sezione Security sta a parte, così chi scorre cercando “devo aggiornare adesso?” la trova in pochi secondi.
Come si tiene aggiornato un CHANGELOG.md?
Scrivi la riga nella stessa pull request della modifica, sotto Unreleased, e sposta la sezione sotto un titolo di versione quando rilasci. Il metodo è tutto qui. Il file invecchia quando la riga viene scritta dopo da qualcun altro, al momento della release, partendo da un elenco di messaggi di commit che non ha scritto.
Due cose fanno attecchire l’abitudine. La prima è un controllo in CI che fa fallire una pull request che tocca src/ senza toccare il changelog, con un’etichetta per saltarlo quando la modifica non ha effetti visibili all’utente; un controllo del changelog come GitHub Action mostra la versione da quaranta righe. La seconda è un passo di release che rinomina Unreleased con versione e data in un solo comando, così nessuno deve ricordarsi di farlo a mano. Chi scrive il changelog spiega come i team risolvono la questione di chi deve scrivere la riga.
Il changelog andrebbe generato dai commit?
La generazione ti dà una bozza completa; non ti dà un changelog. Gli strumenti costruiti sui conventional commits, e le automazioni di release come release-please, leggono i prefissi feat:, fix: e BREAKING CHANGE: e producono un elenco raggruppato con ogni pull request linkata. L’elenco vale quanto i soggetti dei commit, e i soggetti dei commit descrivono il codice.
La via di mezzo che funziona è generare, poi rivedere. Lascia che lo strumento crei la sezione Unreleased dai commit, e fai riscrivere nella pull request di release le righe che un utente leggerà: il sintomo al posto del nome della funzione, l’impostazione che si è spostata al posto del file che è cambiato. Dai conventional commits a un changelog percorre la pipeline, e un generatore di changelog nel browser basta per ottenere una bozza da un git log incollato senza installare nulla.
Cosa non va in CHANGELOG.md?
Refactoring interni, aggiornamenti di dipendenze senza cambi di comportamento, commit solo di test, configurazione della CI e modifiche di formattazione. Appartengono alla cronologia git, dove chiunque ne abbia bisogno può trovarli. Includerli seppellisce le righe che contano e abitua i lettori a saltare il file.
L’altra cosa da lasciare fuori è la versione marketing di una modifica. “Export fulminei” non dice al lettore nulla che possa verificare. “L’export ora è in streaming; i file sopra i 100 MB non vanno più in timeout” sì. Il file è un documento di riferimento, e il tono deve corrispondere: righe brevi, sostantivi concreti, una versione o una data su tutto. Keep a Changelog, messo in pratica copre le parti della specifica che i team lasciano cadere più spesso, e formati di file per changelog spiega quando una sorgente JSON o YAML accanto al file Markdown si guadagna il suo posto.
Un prodotto con una pagina di changelog ha ancora bisogno del file?
Una libreria sì, perché il file è ciò che i registri di pacchetti mostrano e ciò che uno sviluppatore legge offline. Un prodotto SaaS senza artefatto installabile può cavarsela con la sola pagina, visto che i suoi utenti non vedono mai il repository. Molti team tengono entrambi: il file come registro di ingegneria, e una pagina di changelog pubblica scritta a partire da esso per un pubblico più ampio, con i dettagli divisi come descrive changelog vs release notes. Se la pagina è alimentata dal file, tieni il file come fonte di verità e genera la pagina, così c’è un solo posto da modificare.
FAQ
Qual è la differenza tra CHANGELOG.md e le release notes? Il changelog è il registro completo e continuo di ogni modifica rilevante, tenuto nel repository. Le release notes sono un messaggio su una singola release, spesso più breve e riscritto per un pubblico più ampio. Molti progetti pubblicano la sezione del changelog di una versione come sue release notes.
Dove dovrebbe stare CHANGELOG.md? Nella radice del repository, con esattamente quel nome, così GitHub, i registri di pacchetti e gli strumenti di release lo trovano. Un monorepo ne tiene uno per pacchetto, accanto al manifest di ciascun pacchetto.
Dovrei generare CHANGELOG.md dai commit git? Genera la bozza, poi rivedi le righe che un utente leggerà. I messaggi di commit descrivono la modifica al codice; il changelog descrive ciò che un utente nota. Strumenti come conventional-changelog e release-please danno un buon punto di partenza.
Ogni commit ha bisogno di una voce nel changelog? No. Solo le modifiche che un utente del progetto potrebbe notare: nuove capacità, comportamenti cambiati, deprecazioni, rimozioni, correzioni e patch di sicurezza. Refactoring, modifiche ai test e alla CI restano nella cronologia git.
Le affermazioni tecniche di questo articolo non sono state verificate in modo indipendente. Se qualcosa non è corretto, faccelo sapere e lo correggeremo.