Conventional Commits: Messaggi di Commit Professionali e Automatizzabili

I Conventional Commits (in italiano Commit Convenzionali, che suona davvero male 🙂) sono una convenzione standardizzata per la scrittura dei messaggi di commit che trasforma la cronologia Git da un elenco caotico di modifiche a un flusso documentale chiaro per uomini e macchine.

Conventional Commits è una specifica: fornisce un insieme semplice di regole per creare messaggi di commit leggibili, facilitare l’automazione (come la gestione intelligente dei deploy o la generazione automatica di changelog) e migliorare la collaborazione tra sviluppatori.

Perché Adottare i Conventional Commits

L’adozione di questa convenzione offre vantaggi concreti per team e progetti di ogni dimensione:

  • Leggibilità immediata: La struttura standardizzata permette di comprendere a colpo d’occhio il tipo e l’impatto di ogni modifica
  • Automazione del versioning: Tool come semantic-release possono gestire automaticamente il versionamento basandosi sui tipi di commit
  • Integrazione CI/CD intelligente: per esempio, su pipeline che eseguono build, test o deploy solo per determinati tipi di commit (es: feat, fix), ignorando modifiche irrilevanti come docs o chore
  • Collaborazione migliorata: Messaggi uniformi riducono l’ambiguità e facilitano code review e onboarding di nuovi sviluppatori

Struttura di un Conventional Commit

La specifica definisce una struttura precisa composta da tre elementi:

<tipo>[scope opzionale]: <descrizione>

[corpo opzionale]

[footer opzionali]

Componenti Principali

Tipo (obbligatorio): Sostantivo che descrive la categoria della modifica, come feat, fix, docs, seguito da due punti e uno spazio.

Scope (opzionale): Contesto tra parentesi che specifica l’area del progetto interessata, come (api), (db), (ui), (pipeline).

Descrizione (obbligatoria): Frase breve e imperativa che descrive la modifica. Deve essere scritta come se completasse la frase “Questo commit…” o “Se applicato, questo commit…”.

Corpo (opzionale): Spiegazione dettagliata del perché della modifica (non solo del cosa), separato dalla descrizione da una riga vuota, con righe max 72 caratteri.

Footer (opzionali): Metadati come breaking changes (BREAKING CHANGE:), riferimenti a issue (Refs: #123, Fixes: #456) o informazioni per reviewer.

Tipi di Commit Standardizzati

Tipi che Impattano il Versioning

  • feat: Introduce una nuova funzionalità visibile all’utente finale. Incrementa la versione minor in SemVer (es: 1.2.0 → 1.3.0)
  feat(api): aggiungi endpoint /users per ricerca avanzata
  • fix: Corregge un bug che impatta gli utenti. Incrementa la versione patch (es: 1.2.0 → 1.2.1)[6][1]
  fix(db): risolvi connection leak PostgreSQL dopo timeout

Tipi per Manutenzione e Qualità del Codice

  • docs: Modifiche esclusivamente alla documentazione (README, guide, commenti API)[6][2]
  docs(readme): aggiorna sezione installazione con Docker
  • style: Cambiamenti estetici al codice che non alterano la logica (formattazione, indentazione, spazi, punto e virgola mancanti)[2]
  style(pipeline): uniforma indentazione Python a 4 spazi
  • refactor: Ristrutturazione del codice senza modificare il comportamento esterno o l’API[6][2]
  refactor(etl): ottimizza pipeline con chunking Pandas
  • perf: Miglioramenti di performance senza alterare funzionalità[2]
  perf(query): aggiungi indice B-tree su colonna timestamp
  • test: Aggiunta o correzione di test unitari, integration o e2e[6][2]
  test(docker): copri edge case per container networking

Tipi per Infrastruttura e Tooling

  • build: Modifiche a sistemi di build, dipendenze esterne, configurazioni (webpack, npm, Docker)[2]
  build(docker): aggiorna Compose per PostgreSQL 15
  • ci: Cambiamenti a configurazioni e script di CI/CD (GitHub Actions, GitLab CI, CircleCI)[6][2]
  ci(actions): integra commitlint per validazione messaggi
  • chore: Attività di manutenzione minori che non modificano codice sorgente o test (aggiornamento .gitignore, config IDE, dependency bump)[2]
  chore(deps): aggiorna requirements.txt per security patch
  • revert: Annulla un commit precedente, idealmente referenziando l’hash o il titolo del commit annullato[2]
  revert: annulla feat(api): endpoint difettoso

  Refs: commit abc1234
infografica che spiega i conventional commit (struttura, componenti principali, tipi di commit)

Breaking Changes: Gestione delle Rotture di Compatibilità

I breaking changes indicano modifiche che rompono la retrocompatibilità e richiedono attenzione particolare. Possono essere segnalati in due modi:

  1. Indicatore ! dopo tipo/scope:
   feat(api)!: rimuovi campo deprecated user.legacy_id
  1. Footer BREAKING CHANGE: con descrizione dettagliata dell’impatto:
   fix(auth)!: modifica formato token JWT

   BREAKING CHANGE: Il payload JWT ora richiede il campo 'aud'.
   I client esistenti devono aggiornare la libreria auth alla v2.0+

Un breaking change forza automaticamente l’incremento della versione major in SemVer (es: 1.5.3 → 2.0.0), anche se il tipo è fix o altro.

Best Practices per Messaggi di Commit Efficaci

Regole per la Descrizione

  • Forma imperativa presente: “aggiungi”, “correggi”, “rimuovi” (non “aggiunto”, “corretto”, “rimosso”)
  • Lunghezza massima 50 caratteri: Favorisce leggibilità in git log --oneline e interfacce Git (ne esiste solo una da prendere in considerazione: Lazygit! 😀 ❤️)
  • Minuscolo iniziale: La descrizione non deve mai iniziare con lettera maiuscola
  • Nessun punto finale: La descrizione non termina con .
  • Cosa + perché: La descrizione dice cosa cambia, il corpo opzionale spiega perché

Commit Atomici e Scope Contestuali

  • Un commit = una modifica logica: Evitare commit “omnibus” che mescolano refactoring, fix e nuove feature
  • Scope team-specific: Definire scope coerenti con l’architettura del progetto (es: api, db, pipeline, docker, ui) per facilitare ricerche e filtri
  • Referenzia issue tracker: Usare footer per collegare commit a ticket Redmine, Jira, GitHub Issues, ecc: Refs: #123, Fixes: #456, Closes: #789
  • Squash di PR: Quando si fa merge di una pull request, considerare di fare squash dei commit intermedi in un unico Conventional Commit che rappresenta l’intera feature

Oltre i Conventional Commits: Principi Generali

I Conventional Commits si integrano perfettamente con le best practice universali per commit messages di qualità:

  • Commit frequenti: Commit piccoli e frequenti sono più facili da descrivere chiaramente (e da sottoporre a revert in caso di problemi)
  • Testare prima di committare: Ogni commit dovrebbe lasciare la codebase in stato funzionante
  • Usa il corpo per il contesto: Quando la descrizione di 50 caratteri non basta, spiegare nel corpo perché si è fatta quella scelta tecnica, eventuali alternative considerate, e link a discussioni o documentazione (ricordare di mettere nel footer riferimenti).

Risorse e Approfondimenti

  • Specifica ufficiale: conventionalcommits.org – Ottima documentazione completa in italiano
  • Cheatsheet pratica: Gist di qoomon – Reference rapida con esempi
  • Best practices Git commit: cbea.ms/git-commit – Guida approfondita su come scrivere messaggi di commit efficaci (non c’entra niente con i Conventional Commits, ma è un ottimo spunto per migliorare le modalità di ciò che si committa).

Immagine copertina: Biodiversity Heritage Library / American Museum of Natural History Library
Infografica: generata con Gemini Nano Banana Pro.

Pubblicato in Linux, Python.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *