mercoledì 1 ottobre 2025

Git: Annullare le operazioni

Durante lo sviluppo, può capitare di voler annullare una modifica o correggere un errore. Git offre diversi strumenti per gestire queste situazioni, ma è fondamentale utilizzarli con cautela: alcune operazioni di undo non sono reversibili e, se usate in modo improprio, possono comportare la perdita definitiva di lavoro.


Correggere l’ultimo commit con --amend

Uno degli scenari più comuni si verifica quando si effettua un commit troppo presto, dimenticando di includere un file o inserendo un messaggio di commit errato. In questi casi, Git consente di sostituire l’ultimo commit con uno nuovo tramite l’opzione --amend:

git commit --amend

Git prende il contenuto dell’area di staging (index) e lo utilizza per generare un nuovo commit.

Se non sono state aggiunte nuove modifiche dallo scorso commit, verrà riaperto semplicemente l’editor dei messaggi di commit, consentendo di modificarlo.


Esempio pratico

Supponiamo di aver eseguito il commit e di esserci resi conto di aver dimenticato di inserire le modifiche in un file che volevamo aggiungere a questo commit. Possiamo rimediare aggiungendo il file con git add e rieseguire il commit con git commit --amend:

git commit -m "Initial commit"
git add file_dimenticato
git commit --amend

Il repository avrà un solo commit, che include anche file_dimenticato. Il commit precedente viene sovrascritto e sparisce dalla cronologia.


Aspetti importanti da considerare
  • Sostituzione, non modifica 
    - Amend non aggiorna un commit già esistente ma lo sostituisce con un nuovo commit dotato di un nuovo identificativo (SHA-1).
    - Di fatto, è come se il commit precedente non fosse mai esistito.
  • Pulizia della cronologia
    - L’opzione --amend è utile per evitare commit ridondanti.
  • Limitazione: solo commit locali
    - È fortemente sconsigliato eseguire git commit --amend su commit già pubblicati (pushed) in un repository remoto. Infatti, l’operazione riscrive la cronologia e, se accompagnata da un git push --force, può creare conflitti e problemi per gli altri collaboratori.


Tabella di sintesi: git commit --amend

ScenarioComandoRisultato
Modificare solo il messaggio di commitgit commit --amend (senza nuovi file in staging)Sovrascrive il messaggio dell’ultimo commit
Aggiungere file dimenticatigit add file + git commit --amendCrea un nuovo commit che sostituisce il precedente includendo anche file
Commit già pushato sul remotogit commit --amend + git push --forceSconsigliato: riscrive la cronologia e può rompere il lavoro dei collaboratori


Rimuovere un File dall’Area di Staging

Durante il lavoro quotidiano con Git, può capitare di inserire per errore più file nell’area di staging (index) utilizzando un comando troppo generico, come ad esempio:

git add *

In questo caso, se l’obiettivo era committare i file separatamente, è necessario rimuovere uno o più file dallo staging (unstaging), riportandoli allo stato di semplici modifiche nella working directory.

A partire dalla versione 2.23.0, Git ha introdotto il comando git restore, concepito come alternativa più intuitiva e leggibile rispetto a git reset per alcune operazioni di annullamento (undo).

L’obiettivo di questo nuovo comando è semplificare la sintassi e ridurre i rischi legati a usi impropri di git reset, che in passato potevano facilmente portare alla perdita involontaria di dati.

la differenza principale tra git restore e git reset HEAD sta nel loro scopo e nell'ambito d'azione:

  • git restore è un comando moderno e più sicuro, ideato per ripristinare i file nello stato in cui si trovavano in una versione precedente. Agisce sulla working directory (area di lavoro) o sulla staging area (area di "preparazione" prima del commit), ma non modifica la cronologia dei commit. È l'ideale per annullare modifiche locali, che non sono ancora state salvate nella cronologia.
  • git reset HEAD è un comando più vecchio, versatile e potente, che agisce primariamente sulla cronologia dei commit. Sposta il puntatore HEAD a un commit precedente, e di conseguenza, può influenzare l'area di staging e l'area di lavoro a seconda dell'opzione utilizzata (--soft, --mixed, o --hard). È uno strumento più "distruttivo" e va usato con cautela, specialmente su branch condivisi, perché modifica la storia del repository.


Identificare i file in staging con git status

Il comando git status non solo mostra lo stato della working directory e dell’area di staging, ma fornisce anche indicazioni utili su come annullare operazioni indesiderate.

Esempio pratico:

Per individuare il file da rimuovere all'area di staging

git status

git status
FIG 1 - git status

Come si può notare da FIG 1 , Git suggerisce direttamente il comando corretto per rimuovere un file dallo staging.

git restore --staged <file>

Nel nostro caso, per rimuovere il file main.cs dallo staging il comando sarà

git restore --staged main.cs

git restore --staged
FIG 2 - git restore --staged


Lo stesso risultato lo si ottiene con 

git reset HEAD <file>

Il comando git reset è spesso considerato pericoloso, poiché con opzioni come --hard può portare alla perdita definitiva di modifiche locali. Tuttavia, in questo scenario, l’uso di git reset HEAD è sicuro perché non modifica i contenuti della working directory ma agisce esclusivamente sull’indice, rimuovendo il file dallo staging.


Tabella di sintesi: Comandi per gestire lo staging

ComandoEffetto
git add fileAggiunge un file all’area di staging
git reset HEAD fileRimuove il file dallo staging, mantenendo le modifiche nella working directory
git restore --staged fileAlternativa moderna a git reset HEAD file, con la stessa funzione
git reset --hardPericoloso: annulla anche le modifiche nella working directory


 

Annullare le modifiche a un File

Può capitare di accorgersi che le modifiche apportate a un file non sono più necessarie e che si desidera ripristinare il contenuto all’ultima versione tracciata da Git (ossia l’ultima presente nell’area di staging o nel commit più recente).

In questi casi, Git mette a disposizione due comandi storicamente equivalenti, ma con differenze importanti: git restore (introdotto in Git ≥ 2.23.0) e git checkout (metodo tradizionale).


Esempio pratico con git restore

Supponiamo di aver modificato il file main.cs. Eseguiamo il comando

git status

git status
FIG 3 - git status

Per annullare le modifiche non salvate:

git restore main.cs

Dopo il comando, il file torna allo stato dell’ultimo commit o staging, eliminando definitivamente i cambiamenti locali.

git restore
FIG 4 - git restore


Esempio pratico con git checkout

git checkout -- main.cs

Anche in questo caso il file viene ripristinato, cancellando le modifiche locali.

git checkout
FIG 5 - git checkout



Differenze tra git restore e git checkout

Caratteristicagit restoregit checkout
DisponibilitàIntrodotto in Git ≥ 2.23.0Presente in tutte le versioni di Git
ObiettivoProgettato specificamente per annullare modifiche ai file (working directory e staging)Comando multifunzione (cambio branch, ripristino file, navigazione)
Chiarezza sintatticaPiù leggibile e autoesplicativo (restore indica chiaramente lo scopo)Sintassi più generica e meno intuitiva
Rischio di confusioneRidotto: il comando è dedicato solo al ripristinoElevato: git checkout gestisce operazioni molto diverse tra loro
Best PracticeConsigliato nei workflow moderni per annullare modifiche localiAncora valido, ma da usare con cautela per evitare ambiguità


Attenzione

  • Entrambi i comandi cancellano in modo irreversibile le modifiche locali non ancora salvate in un commit.
  • Prima di utilizzarli, è opportuno chiedersi se le modifiche possano essere utili in futuro.
  • In alternativa, si può ricorrere a git stash o a un nuovo branch, salvando temporaneamente i cambiamenti senza perderli.

È importante ricordare che soltanto ciò che è stato effettivamente sottoposto a commit può essere recuperato; le modifiche non salvate andranno invece perse in maniera definitiva.

In Git, i dati oggetto di commit risultano quasi sempre recuperabili, anche qualora appartengano a rami successivamente eliminati oppure siano stati sovrascritti tramite l’opzione --amend. Tutte le modifiche non ancora committate e andate perse non potranno, con ogni probabilità, essere ripristinate.


Best Practice

  • Usare git restore nei progetti moderni: più chiaro e meno soggetto a errori.
  • Evitare git checkout -- <file> se non strettamente necessario: mantiene la retrocompatibilità, ma può confondere.
  • Ricorrere a git stash o ai branch per soluzioni temporanee: ideale se non si vuole perdere il lavoro fatto.



domenica 28 settembre 2025

Git: Consultazione della Cronologia dei Commit

Dopo aver effettuato diversi commit, oppure quando si clona un repository con una cronologia già esistente, è fondamentale poter analizzare lo storico delle modifiche.

Lo strumento principale messo a disposizione da Git per questo scopo è il comando git log, che consente di ispezionare in dettaglio l’evoluzione di un progetto.

Il comando più semplice è:

git log

L’output predefinito elenca i commit in ordine cronologico inverso, mostrando per ciascun commit:

  • l’hash SHA-1 univoco
  • l’autore con email
  • la data
  • il messaggio di commit

git log
FIG 1 - git log

Opzioni utili di git log

Git mette a disposizione un’ampia gamma di opzioni per adattare l’output alle proprie esigenze.

1. Mostrare le modifiche introdotte da ciascun commit
git log -p -2
  • L’opzione -p (o --patch) visualizza le differenze introdotte.
  • Il parametro -2 limita l’output agli ultimi due commit.
  • Utile in fase di code review o per analizzare l’evoluzione del codice.
git log -p -2
FIG 2 - git log -p -2

2. Visualizzare statistiche sintetiche

git log --stat

Mostra i file modificati, il numero di righe aggiunte/rimosse e un riepilogo finale.
git log --stat
FIG 3 - git log --stat
git log --shortstat
Questo comando fornisce un riassunto molto conciso per ogni commit. Mostra un'unica riga con il conteggio totale dei file modificati e il numero totale di righe aggiunte e cancellate. Non elenca i nomi specifici dei file.

3. Formattazione personalizzata

Consente di definire un formato personalizzato dell’output, utile per generare report o output leggibili da script.
git log --pretty=format:"%h - %an, %ar : %s"

Segnaposto principali

SegnapostoDescrizione
%HHash completo del commit
%hHash abbreviato
%THash dell'albero
%tHash dell'albero abbreviato
%PHash dei genitori
%pHash dei genitori abbreviati
%anNome autore
%aeEmail autore
%adData autore (formato configurabile con --date=)
%arData autore relativa (es. “2 weeks ago”)
%cnNome committer
%ceEmail committer
%cdData del committer
%crData del committer, relativa
%sMessaggio del commit
git log --pretty=format
FIG 4 - git log --pretty=format

4. Output compatti
  • git log --oneline
    commit in una sola riga (hash abbreviato + messaggio).
  • git log --pretty=short|full|fuller
    diversi livelli di dettaglio.
  • git log --abbrev-commit
    mostra solo le prime cifre dell’hash.
git log --oneline
FIG 5 - git log --oneline

5. Rappresentazione grafica

Visualizza un grafico ASCII che illustra la struttura di branch e merge, molto utile in repository complessi.
git log --graph
git log --graph
FIG 6 - git log --graph

Opzioni per limitare l'output di git log

Oltre alle opzioni di formattazione, il comando git log supporta numerose opzioni di limitazione, che consentono di filtrare i commit mostrati.
Queste opzioni sono utili per concentrarsi su un intervallo temporale, un autore, un file specifico o persino su modifiche particolari al codice.

1. Limitazione numerica

Per visualizzare solo gli ultimi n commit:

git log -2
Mostra solo gli ultimi due commit.
git log -2
FIG 7 - git log -2



2. Limitazione temporale

È possibile filtrare i commit in base a date assolute o relative:

git log --since=2.weeks
git log --since="2025-01-01" --until="2025-01-31"


--since / --after  
commit successivi a una certa data.

--until / --before 
commit precedenti a una certa data.

Esempi validi di date:
"2008-01-15" (formato ISO)
"2 years 1 day 3 minutes ago" (relativo)



3. Filtrare per autore o committer

git log --author="Alice"
git log --committer="Bob"

--author  
mostra commit scritti da un certo autore.

--committer
mostra commit applicati da uno specifico committer.

É possibile utilizzare più di una regola --author o --grep contemporaneamente.
Con l’opzione --all-match, Git mostrerà solo i commit che soddisfano tutti i criteri.



4. Ricerca nei messaggi di commit

git log --grep="bugfix"

Mostra i commit che hanno "bugfix" nel messaggio di commit.
Può essere combinato con --author e --since per ricerche più precise.



5. Pickaxe: cercare modifiche nel codice

git log -S function_name

L’opzione -S (detta pickaxe) trova i commit in cui cambia il numero di occorrenze di una stringa (es. aggiunta o rimozione di una funzione).
Ottimo per capire quando e perché è stata introdotta o rimossa una porzione di codice.



6. Limitazione per file o directory

git log -- path/to/file

Mostra solo i commit che hanno modificato un file o una directory specifica.
Per separare chiaramente le opzioni dal percorso si usa --:

git log --since="2025-01-01" -- path/to/file



7. Evitare i merge commit

In repository con workflow basati su merge, la cronologia può risultare affollata.
Per nascondere i merge commit non informativi:

git log --no-merges


Tabelle riepilogative delle opzioni comuni

OpzioneDescrizione
-p o --patchMostra le differenze introdotte da ciascun commit
--statRiepilogo file modificati e righe aggiunte/rimosse
--shortstatSolo il riepilogo numerico (senza elenco file)
--name-onlyElenco dei file modificati
--name-statusElenco file + stato (A=Added, M=Modified, D=Deleted)
--abbrev-commitHash abbreviati
--relative-dateDate in formato relativo (“2 days ago”)
--graphGrafico ASCII della cronologia
--prettyFormati alternativi (oneline, short, full, fuller, format)
--onelineAlias di --pretty=oneline --abbrev-commit. Mostra ogni commit su una singola riga 


Opzioni di filtro

OpzioneDescrizione
-n <numero>Limita il numero di commit visualizzati all'ultimo <numero> specificato
--author="<pattern>"Filtra i commit in base all'autore. Accetta anche espressioni regolari.
--committer="<pattern>"Filtra i commit in base al committer.
--grep="<pattern>"Filtra i commit in base a un pattern nel messaggio del commit.
--since="<data>"Visualizza i commit a partire da una data specificata("2 weeks ago", "2023-01-01", "yesterday").
--until="<data>"Visualizza i commit fino a una data specificata.
--after="<data>"Alias di --since
--before="<data>"Alias di --until
<file-o-cartella>Mostra solo i commit che hanno modificato un file o una cartella specifica
--mergesMostra solo i commit di merge.
--no-mergesEsclude i commit di merge dalla visualizzazione.


Opzioni di navigazione

OpzioneDescrizione
--reverseLimita il numero di commit visualizzati all'ultimo <numero> specificato
<start>..<end>Filtra i commit in base all'autore. Accetta anche espressioni regolari.
-S"<stringa>"
o --all-match-S"<stringa>"
Mostra i commit che hanno introdotto o rimosso una riga contenente una stringa specifica. Utile per il debugging.
-G"<regex>"Simile a -S, ma usa un'espressione regolare per cercare le modifiche nel contenuto dei file



Differenza tra autore e committer

  • Autore (Author): chi ha scritto originariamente la modifica.
  • Committer: chi ha applicato la modifica al repository (può coincidere con l’autore o essere un maintainer che ha accettato una patch).

Questo permette di riconoscere sia chi ha prodotto il codice sia chi ne ha garantito l’integrazione


Esempio avanzato

Visualizzare i commit:

  • scritti da Giovanni Lubrano Lavadera,
  • nel mese di novembre 2024,
  • che non siano merge commit,
  • relativi alla directory test/
git log --pretty="%h - %s" \ --author="Giovanni Lubrano Lavadera" \ --since="2024-11-01" \ --before="2024-12-01" \ --no-merges -- test/




giovedì 25 settembre 2025

Git: Gestione dello spostamento e rinomina dei file

A differenza di molti altri sistemi di controllo versione (VCS), Git non memorizza esplicitamente i metadati relativi allo spostamento o alla rinomina dei file.

Quando un file viene rinominato o spostato, Git non registra direttamente questa operazione, ma è in grado di riconoscerla in maniera implicita analizzando le differenze tra le versioni dei file al momento del commit.

Nonostante ciò, Git fornisce il comando git mv, che semplifica l’operazione di rinomina o spostamento di un file, integrando in un’unica istruzione le operazioni necessarie.


Esempio di utilizzo

git mv Readme.txt ReadmeFirst.txt

git status

L'output sarà quello visualizzato in FIG 1.

Rinomina file con git mv
FIG 1 - Rinomina file con git mv

In questo caso, Git riconosce il file come rinominato e lo segnala chiaramente nello staging area.

Il comando git mv è una scorciatoia che racchiude in un’unica istruzione tre operazioni normalmente necessarie:

  1. Rinomina a livello di filesystem
    mv Readme.txt ReadmeFirst.txt 
  2. Rimuove il vecchio file dall’indice
    git rm Readme.txt
  3. Aggiunge il nuovo file all’indice
    git add README

Il risultato finale è identico: Git rileva la rinomina al momento del commit, indipendentemente da come sia stata eseguita.


Vantaggi dell’uso di git mv

  • Maggiore semplicità: un solo comando invece di tre.
  • Maggiore chiarezza: rende esplicita l’intenzione di rinominare o spostare un file.
  • Integrazione fluida nello staging: evita errori di dimenticanza (ad esempio eseguire mv ma non aggiornare l’indice).


Best Practice

  • Utilizzare git mv per rendere più chiaro lo storico dei comandi ed evitare passaggi manuali.
  • In progetti complessi, verificare sempre con git status che la rinomina sia stata rilevata correttamente.
  • Ricordare che Git determina la rinomina per similarità di contenuto: se il file rinominato è stato pesantemente modificato, potrebbe non essere riconosciuto automaticamente come rename ma come delete + add.



martedì 23 settembre 2025

Git: Rimozione dei file

La gestione della rimozione dei file in Git non si limita a cancellarli dal file system: occorre infatti aggiornare anche l’indice (staging area) affinché il VCS tenga traccia della loro eliminazione. A questo scopo si utilizza il comando git rm, che rimuove un file sia dalla working directory sia dall’area di staging, garantendo così che il cambiamento venga registrato nel prossimo commit.

Se invece un file viene eliminato manualmente dal file system (ad esempio con rm nomefile in Linux/Mac o del nomefile in Windows), Git rileverà la cancellazione come una modifica non tracciata e la segnalerà con lo stato deleted nel comando git status. In questo scenario, per allineare il repository occorre esplicitamente eseguire:

git rm nomefile

git commit -m "Remove nomefile"

git rm
FIG 1 - git rm


Opzioni principali di git rm

  • git rm file
    Rimuove il file dalla working directory e dall’indice, pronto per essere eliminato con il commit successivo.
  • git rm -f file (force)
    Utilizzato quando il file modificato o già in staging non può essere rimosso normalmente. Serve a prevenire la perdita di dati non ancora salvati in un commit.
  • git rm -r nomecartella
    Rimuove la cartella dalla working directory e dall’indice. La cartella e i file contenuti verranno eliminati con il commit successivo.
  • git rm --cached file
    Rimuove il file solo dall’indice, mantenendolo nel file system locale. È utile quando si vogliono escludere file già tracciati (ad esempio log, binari o configurazioni locali) che dovrebbero essere ignorati in futuro tramite .gitignore.
  • Supporto a directory e pattern
    È possibile passare intere cartelle o utilizzare glob patterns:
    git rm log/\*.log     # rimuove tutti i file .log in log/  
    git rm *~            # rimuove tutti i file temporanei terminanti con ~

    Attenzione: occorre fare escaping (\*) se si vuole che il pattern venga interpretato da Git e non dalla shell.


Tabella di confronto: modalità di rimozione

Comando Effetto sul file system Effetto sull’indice (staging) Caso d’uso tipico
rm file / del file Elimina il file solo dal disco Segnalato come deleted ma non ancora tracciato Eliminazione manuale, da completare con git rm
git rm file Elimina dal disco e dall’indice File rimosso e pronto al commit Rimozione standard di file tracciati
git rm -r cartella Elimina dal disco e dall’indice Cartella rimossa e pronto al commit Rimozione standard di cartelle tracciate
git rm -f file Forza l’eliminazione anche se modificato File rimosso forzatamente Prevenire conflitti con file non ancora committati
git rm --cached file Mantiene il file nel disco Rimosso dall’indice Escludere file dal versionamento (es. log, build, config locali)
git rm pattern (es. *.log) Elimina più file secondo il pattern Tutti i file corrispondenti rimossi Pulizia massiva di file generati automaticamente

 

Best practice

  • Prima di utilizzare git rm -f, verificare se le modifiche devono essere salvate: in caso positivo, effettuare un commit preventivo.
  • Utilizzare git rm --cached in combinazione con un aggiornamento del .gitignore, per evitare di reintrodurre accidentalmente file indesiderati.
  • Per rimuovere directory intere, aggiungere l’opzione -r (git rm -r nomecartella).
  • In ambienti Windows, ricordare che del elimina il file solo dal disco: per rimuoverlo correttamente dal repository è necessario seguire con git rm.



domenica 21 settembre 2025

Git: Commit senza passare dall’Area di Staging

L’area di staging rappresenta uno degli elementi chiave di Git, in quanto consente di preparare con precisione il contenuto di ogni commit. Tuttavia, in determinati contesti operativi, questa fase intermedia può risultare superflua e introdurre complessità non necessarie.

Per semplificare il flusso di lavoro, Git mette a disposizione un’opzione che consente di saltare lo staging: l’utilizzo del flag -a insieme al comando git commit. Il comando:

git commit -a -m "Messaggio del commit"

esegue automaticamente lo staging di tutti i file già tracciati (tracked) che risultano modificati o eliminati, evitando quindi la necessità di richiamare manualmente git add.

Esempio pratico

Supponiamo di trovarci nella situazione mostrata in FIG1 in cui il file Readme.txt, tracciato, è stato modificato ma non aggiunto all'area di staging e il file Leggimi.txt non tracciato.

Git status
FIG 1 - Git status

Eseguendo il comando

git commit -a -m "Aggiunte note a Readme.txt"

il file Readme.txt,  pur non essendo stato esplicitamente aggiunto con git add, viene comunque incluso nel commit grazie al flag -a.

git commit -a
FIG 2 - git commit -a

Il file Leggimi.txt non viene incluso nel commit in quanto si tratta di un file nuovo non tracciato.

Stato dei file dopo gti commit -a
FIG 3 - Stato dei file dopo gti commit -a


Limitazioni importanti

L’opzione -a funziona solo per i file già tracciati. Ciò significa che:

  • i nuovi file (non ancora aggiunti con git add) non saranno inclusi nel commit;
  • i file ignorati tramite .gitignore continueranno a essere esclusi;
  • i file rimossi manualmente dal filesystem vengono comunque registrati come eliminati.


Vantaggi e rischi

L’utilizzo del flag -a può risultare particolarmente utile in contesti in cui si lavora su commit veloci e incrementali, riducendo i passaggi necessari. Tuttavia, presenta anche alcune criticità:

Vantaggi

  • Semplificazione del flusso di lavoro.
  • Minore rischio di dimenticare file modificati già tracciati.
  • Maggiore rapidità in operazioni di manutenzione o correzioni veloci (hotfix).

Rischi

  • Possibile inclusione di modifiche indesiderate (ad esempio righe di debug temporanee).
  • Minore controllo fine sul contenuto del commit rispetto allo staging manuale.


Best Practice

Per utilizzare in modo efficace git commit -a, è consigliabile:

  • Usarlo solo per commit semplici e poco critici (es. piccole correzioni o aggiornamenti rapidi).
  • Evitare di utilizzarlo in commit complessi, dove è preferibile selezionare manualmente i file da includere nello staging.
  • Combinare con git diff o git diff --staged per verificare le modifiche prima di finalizzare il commit.
  • Non dimenticare i file nuovi, che richiedono comunque un git add esplicito.


Comando Funzionamento File inclusi nel commit Quando utilizzarlo
git commit Crea un commit solo con i file già presenti nello staging Solo i file aggiunti esplicitamente con git add Quando si desidera controllo totale sul contenuto del commit.
git commit -a Esegue automaticamente lo staging di tutti i file già tracciati modificati o eliminati, prima del commit. File già tracciati (modificati o rimossi), non i nuovi file Per modifiche rapide o manutenzioni veloci, senza passare dallo staging.
git commit -am "msg" Combina il comportamento di -a con l’aggiunta del messaggio inline (-m). Come -a, ma con messaggio direttamente in linea Per commit veloci con messaggio breve (es. hotfix, piccole correzioni).




mercoledì 17 settembre 2025

Git: Commit

Una volta predisposta l’area di staging con le modifiche desiderate, è possibile procedere alla creazione di un commit. È importante ricordare che eventuali file ancora non aggiunti allo staging, ovvero quelli che sono stati creati o modificati ma per i quali non è stato eseguito il comando git add, non verranno inclusi nel commit corrente. Tali file rimarranno nello stato di modified nella working directory e potranno essere aggiunti successivamente.

Supponiamo, ad esempio, che l’ultimo comando git status abbia mostrato che tutte le modifiche risultano già correttamente inserite nello staging. In questo caso, è possibile eseguire il commit con il comando più semplice:

git commit

L’esecuzione del comando apre l’editor di testo configurato come predefinito (ad esempio Vim o Emacs), determinato dalla variabile d’ambiente EDITOR della shell. Tale editor può essere modificato a piacere tramite:

git config --global core.editor "<nome_editor>"


All’interno dell’editor viene mostrato un template che include:

  • una riga vuota in cui inserire il messaggio di commit;
  • un riepilogo delle modifiche in formato commentato, generato automaticamente da git status.

Le righe precedute dal carattere # sono considerate commenti e non vengono salvate nel commit. È possibile rimuoverle o lasciarle come promemoria.

git commit
FIG 1 - git commit

Per avere un contesto ancora più dettagliato, è possibile utilizzare l’opzione -v:

git commit -v

git commit -v
FIG 2 - git commit -v

In questo caso, oltre al riepilogo, viene mostrato anche il diff delle modifiche, consentendo di verificare con precisione quali linee di codice saranno incluse nel commit.


In alternativa, è possibile specificare il messaggio direttamente da riga di comando con l’opzione -m:

git commit -m "Modifica Projects1.cs"

Il messaggio deve essere chiaro, conciso e descrittivo, in modo da facilitare la comprensione della cronologia del progetto. È buona pratica adottare convenzioni uniformi all’interno del team di sviluppo (ad esempio includere ID di ticket o issue).


Output del commit

Dopo la conferma, Git fornisce un breve riepilogo contenente:
  • il branch su cui è stato eseguito il commit (es. master o main);
  • l’hash SHA-1 che identifica in maniera univoca il commit;
  • il numero di file modificati;
  • le statistiche sulle linee aggiunte e rimosse.

Output commit
FIG 3 - Output commit

Il commit come snapshot

È fondamentale sottolineare che un commit non registra semplicemente le differenze, ma rappresenta un vero e proprio snapshot dello stato del progetto nell’area di staging in quel momento. Tutti i file non inclusi nello staging rimarranno inalterati nella working directory e potranno essere oggetto di un commit successivo.

Ogni commit diventa così una tappa storica nel ciclo di vita del progetto, alla quale è possibile tornare in caso di necessità, oppure confrontarla con versioni più recenti per analizzare l’evoluzione del codice.


Best Practice per i Messaggi di Commit

Un commit efficace non riguarda solo il codice, ma anche la documentazione della modifica. Scrivere messaggi chiari e coerenti consente a chiunque (incluso il sé stesso futuro) di comprendere rapidamente la storia del progetto.

Ecco alcune linee guida ampiamente riconosciute:

1. Usare un titolo breve e descrittivo

  • Limitare la prima riga a 50 caratteri circa.
  • Utilizzare il modo imperativo (es. “Fix bug”, “Add feature”, “Refactor code”) per descrivere l’azione.

2. Aggiungere una descrizione più dettagliata se necessario

  • Inserire una riga vuota dopo il titolo.
  • Fornire ulteriori spiegazioni sul perché della modifica, non solo sul cosa è stato cambiato.

3. Fare commit atomici

  • Ogni commit deve contenere una modifica logica unica e indipendente.
  • Evitare commit che mescolano refactoring, correzioni e nuove funzionalità.

4. Riferirsi a ticket o issue

  • Quando si lavora in team con strumenti come Jira, GitHub o GitLab, citare l’ID del ticket o il numero dell’issue. Ad esempio: 
    git commit -m "Fix #182: corregge l’errore di serializzazione JSON"

5. Seguire convenzioni standardizzate

  • Molti team adottano lo schema dei Conventional Commits, che prevede prefissi come:
    feat: per nuove funzionalità
    fix: per bugfix
    docs: per modifiche alla documentazione
    refactor: per miglioramenti interni al codice
    test: per aggiunta o modifica di test

    Esempio:
    feat(auth): aggiunta autenticazione tramite OAuth2

6. Evitare messaggi generici

  • Non usare commit come "update", "fix bug", "varie modifiche".
  • Essere sempre specifici.




lunedì 15 settembre 2025

Git: Visualizzare le modifiche tracciate e non tracciate

Il comando git status fornisce una panoramica dello stato del repository, ma talvolta può risultare troppo generico: mostra quali file sono stati modificati, senza però evidenziare nel dettaglio quali righe siano cambiate.

Per ottenere una visione più approfondita delle differenze, è possibile utilizzare il comando git diff, che permette di ispezionare direttamente le modifiche a livello di contenuto.

In particolare, il comando git diff consente di ottenere risposte a due quesiti fondamentali:
  • Quali modifiche sono state effettuate ma non ancora aggiunte all’area di staging?
  • Quali modifiche risultano già presenti nello staging e che, di conseguenza, verranno incluse nel prossimo commit?


Differenze tra file modificati e staging area

Supponiamo, ad esempio, di modificare il file Readme.txt e di aggiungerlo allo staging con git add, mentre contestualmente modifichiamo il file Project1.cs senza però metterlo in staging.

Un comando git status restituirà un output simile a quello mostrato in FIG 1

git status
FIG 1 - git status


In questa situazione, se eseguiamo:

git diff

Git ci mostrerà le modifiche presenti nel working directory ma non ancora aggiunte allo staging. Questo output, detto patch, include esattamente le righe aggiunte (+) e rimosse (-) nei file.

git diff
FIG 2 - git diff

Al contrario, se desideriamo visualizzare le differenze già pronte per il prossimo commit, dobbiamo usare:

git diff --staged

oppure, in alternativa:

git diff --cached

(--staged e --cached sono sinonimi). Questo comando confronta le modifiche presenti nello staging con l’ultimo commit registrato.

git diff --staged
FIG 3 - git diff --staged

Caso pratico: modifiche sia staged che unstaged

Può accadere che lo stesso file venga modificato, aggiunto allo staging e poi ulteriormente modificato senza essere riaggiunto. In questo caso, git diff e git diff --staged mostrano rispettivamente:

  • le differenze non ancora aggiunte,
  • le differenze già pronte per essere salvate nel commit successivo.

Questo scenario è comune durante lo sviluppo, e l’uso combinato dei due comandi consente di avere il massimo controllo su ciò che sarà effettivamente registrato nella cronologia del progetto.

Nota importante: È bene sottolineare che git diff, se usato da solo, non mostra tutte le modifiche rispetto all’ultimo commit, ma solo quelle ancora unstaged.

Se tutte le modifiche sono state aggiunte allo staging, il comando non produrrà alcun output. In questi casi, l’opzione --staged è necessaria per visualizzare le differenze.


Utilizzo di strumenti esterni: git difftool

Per chi preferisce un’interfaccia grafica o un visualizzatore esterno, Git mette a disposizione il comando git difftool. Questo consente di analizzare le differenze utilizzando software come vimdiff, meld, kdiff3, o strumenti commerciali come Beyond Compare e Araxis Merge.

git difftool, richiesta avvio tool per la comparazione
FIG 4 - git difftool, richiesta avvio tool per la comparazione


Differenze nel file Project1.cs
FIG 5 - Differenze nel file Project1.cs

Per scoprire quali strumenti sono disponibili sul proprio sistema:

git difftool --tool-help

È possibile configurare uno strumento di default nel file di configurazione globale:

git config --global diff.tool meld

Da quel momento, eseguendo git difftool senza ulteriori opzioni, Git aprirà automaticamente le differenze nell’applicativo scelto.


Best practices

  • Usare spesso git diff: controllare con regolarità le differenze riduce il rischio di commettere modifiche indesiderate.
  • Verificare prima di committare: un git diff --staged prima di eseguire il commit assicura che solo le modifiche realmente volute vengano salvate nella cronologia.
  • Configurare strumenti grafici: in progetti complessi, visualizzatori esterni possono facilitare l’analisi di modifiche estese.


Di seguito una tabella riepilogativa dei principali comandi di Git usati per analizzare lo stato dei file e le modifiche:

Comando Scopo principale Cosa mostra Quando usarlo Output
git status Fornisce una panoramica dello stato del repository Elenco dei file modificati, non tracciati, staged o unstaged Per avere una visione generale prima di committare Testuale, descrittivo (ma non mostra le differenze riga per riga)
git diff Mostra le modifiche non ancora aggiunte allo staging (unstaged) Differenze tra working directory e staging area Per sapere esattamente cosa è cambiato nei file non ancora aggiunti Patch con righe aggiunte (+) e rimosse (-)
git diff --staged (o git diff --cached) Mostra le modifiche già aggiunte allo staging Differenze tra staging area e ultimo commit Per verificare cosa verrà incluso nel prossimo commit Patch dettagliata delle modifiche staged
git difftool Visualizza le differenze con uno strumento esterno Identico a git diff (staged o unstaged, a seconda dei parametri), ma in interfaccia grafica o editor Per analizzare modifiche complesse o in progetti estesi Dipende dallo strumento scelto (es. vimdiff, meld, Beyond Compare, ecc.)