Generare Messaggi di Commit Automaticamente (con AI) in Shell

Scrivere messaggi di commit chiari e consistenti è una buona pratica, ma spesso la cosa che viene saltata quando si lavora velocemente e non si ha tempo e modo di scrivere il messaggio in modo articolato (oppure non in conventional style 😉).

Ho automatizzato questo passaggio tramite gcommit, una piccola funzione Bash che legge la staging area di Git e delega la generazione del messaggio a un LLM; il tutto direttamente dal terminale.


Il Problema e l’Idea

Un buon messaggio di commit dovrebbe rispettare una convenzione, descrivere cosa cambia e perché, e farlo in modo sintetico. Tutto questo richiede attenzione e tempo, risorse che a fine sessione di debug tendono a scarseggiare.

L’idea è semplice:
il git diff --cached contiene, quasi sempre, già tutta l’informazione necessaria per descrivere le modifiche. Perché non passarne l’output a un LLM chiedendo la generazione di un messaggio di commit fatto bene?


llm: LLM dalla Riga di Comando

llm è uno strumento CLI open-source sviluppato da Simon Willison (il co-creatore di Django) e parte del progetto Datasette. Permette di interagire con decine di modelli (OpenAI, Anthropic Claude, Google Gemini, etc) sia tramite API remote che in locale tramite plugin (es. llm-ollama).

L’utilizzo base è minimalista:

# Prompt semplice
llm "Spiega questo errore: segmentation fault"

# Pipe da stdin
cat myfile.py | llm -s "Spiega questo codice"

# Specifica un modello
llm -m claude-4-opus "Dimmi qualcosa sulle turnip"

È scritto in Python. L’installazione può quindi essere fatta direttamente tramite pip, pipx, uv:

pipx install llm          # consigliato per isolare le dipendenze
uv tool install llm       # consigliato per isolare le dipendenze
llm keys set openai       # configura la chiave API

I Template in llm

llm supporta i template: file YAML riutilizzabili che combinano un system prompt, un modello di default e opzioni preconfigurate .

Un template viene invocato con il flag -t:

cat myfile.py | llm -t code-review

Per il workflow dei commit, ho creato un template chiamato git-commit:

llm templates edit git-commit

Il contenuto del template è il seguente:

 Generate a commit message following the "Conventional Commits" standard.
  Analyze the given git diff input.
  Use this format:
  `<type>(<scope>): <brief description>`

  `<body of the message with technical explanation>`

  Allowed types: feat, fix, docs, style, refactor, perf, test, chore.

  Use english to generate di commit message, also if the codebase is in other language.

Ultimamente sto utilizzando DeepSeek. Ho settato su llm un alias e chiamo il modello con il parametro
-m ds

Quindi, per esempio, lanciando:

llm -m ds -t git-commit "Testo di input"

sto dicendo a llm di utilizzare, sul testo di input fornito, il modello DeepSeek con il template git-commit.


La Funzione gcommit

La funzione può essere inserita nel .bashrc e si compone di tre passi logici:

gcommit() {
  # 1. Controlla se ci sono file in stage
  if git diff --cached --quiet; then
    echo "⚠️  Nessun file in stage. Fai 'git add <files>' prima di lanciare gcommit."
    return 1
  fi

  echo -e "🤖 \033[1;30mGenerazione del messaggio di commit in corso...\033[0m\n"

  # 2. Passa il diff all'LLM usando il template git-commit
  COMMIT_MSG=$(git diff --cached | llm -m ds -t git-commit)

  # 3. Stampa il risultato in turchese
  echo -e "\033[1;36m$COMMIT_MSG\033[0m\n"
}

Step 1 — Cerca le modifiche:
Staging vuoto → git diff –cached –quiet esce con 0 → la condizione è vera → viene stampato il warning e la funzione termina
Staging non vuoto → esce con 1 → la condizione è falsa → si prosegue con la generazione del messaggio

Step 2 — Generazione: git diff --cached produce il diff completo dei file in stage, che viene passato via pipe a llm. Il flag -m ds specifica il modello, -t git-commit applica il template con il system prompt.

Step 3 — Output: Il messaggio viene stampato in ciano bold (\033[1;36m) per distinguerlo visivamente dall’output normale del terminale.

Il messaggio non viene committato automaticamente.
Ma si può ovviamente pensare di evolvere lo script prevedendo anche il commit di quanto proposto.
Io, per ora, preferisco andare a mano.


Flusso di Utilizzo Tipico

L’utilizzo del tutto è semplice. Quando ho i file in staging lancio il comando gcommit e ottengo in automatico il messaggio che desideravo.

Esempio:

# 1. Modifica i file
nvim src/parser.py

# 2. Stage delle modifiche
git add src/parser.py

# 3. Genera il messaggio
gcommit
# → 🤖 Generazione del messaggio di commit in corso...
# → refactor(parser): extract token validation into separate method
# →
# → Move inline validation logic into `validate_token()` to improve
# → readability and allow independent unit testing.

# 4. Committa
git commit -m "refactor(parser): extract token validation into separate method bla bla bla"

Estensioni Possibili (suggerite dal mio llm)

  • Auto-commit con conferma: aggiungere un read -p "Confermi? [y/N] " e committare automaticamente se si risponde y
  • Modello configurabile: accettare un parametro opzionale per sovrascrivere il modello (gcommit gpt-4o)
  • Supporto multi-lingua: parametrizzare la lingua del messaggio nel template
  • Integrazione con fzf: mostrare più proposte e scegliere interattivamente

Immagine copertina: The vaudeville star Fritzi Ridgeway, showing what it takes to melt a snowman (immagine colorizzata con AI)

Pubblicato in AI, Linux, Python.

Lascia un commento

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