W3docs

git diff

Scopri il comando git diff, come leggerne l'output, evidenziare le modifiche e confrontare file e branch in Git.

Cosa fa git diff

Il comando git diff mostra esattamente cosa è cambiato, riga per riga, tra due sorgenti nel tuo progetto. Prende due insiemi di dati e stampa le differenze tra loro come una patch.

Le due sorgenti possono essere qualsiasi coppia tra: la tua working tree (i file che stai modificando in questo momento), la staging area (l'indice, ciò che git add ha acquisito) e qualsiasi snapshot committato. Poiché ogni altro comando Git ti dice solo che qualcosa è cambiato, git diff è lo strumento che ti dice cosa è cambiato prima di fare lo stage o il commit.

Viene comunemente usato insieme a git status e git log per ispezionare lo stato di un repository Git: git status elenca i file modificati, mentre git diff mostra il contenuto di tali modifiche.

gitdiff

Quali due sorgenti vengono confrontate

La forma del comando determina cosa viene confrontato:

ComandoConfronta
git diffWorking tree vs. staging area (modifiche non in stage)
git diff --stagedStaging area vs. ultimo commit (ciò che git commit registrerebbe)
git diff HEADWorking tree vs. ultimo commit (tutte le modifiche non committate)
git diff <commit> <commit>Un commit rispetto a un altro
git diff <branch> <branch>Le punte di due branch

Un git diff senza argomenti mostra solo ciò che non hai ancora messo in stage con git add. Questo è l'errore più comune: se hai già eseguito git add, git diff sembra vuoto anche se hai delle modifiche — usa git diff --staged per vederle.

Leggere l'output di diff

Un diff ha diverse parti distinte. Le sezioni seguenti ne costruiscono uno e spiegano ogni riga.

Formato dell'output grezzo

Dai un'occhiata ai comandi qui sotto per creare un semplice repository:

mkdir test_repo
cd test_repo
touch test.txt
echo "this is a git diff test example" > test.txt
git init .
#Initialized empty Git repository in /Users/kev/code/test/.git/
git add test.txt
git commit -am "add diff test file"
#[master (root-commit) 9e2dcac] add diff test file
#1 file changed, 1 insertion(+)
#create mode 100644 test.txt

Se vuoi che git diff produca output, devi modificare il contenuto di test.txt dopo averlo committato. Esegui il seguente comando:

echo "this is a diff example" > test.txt

Solo ora possiamo visualizzare un diff e discutere l'output. Eseguendo git diff si otterrà il seguente risultato:

diff --git a/test.txt b/test.txt
index 6b0c6cf..b37e70a 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Sorgenti di input del diff

La prima riga nomina le due sorgenti che vengono confrontate. In questo caso a/test.txt (la versione "prima") e b/test.txt (la versione "dopo") vengono passate al diff. I prefissi a/ e b/ identificano sempre i due lati, anche quando si tratta dello stesso file.

diff --git a/test.txt b/test.txt

Metadati

Questa riga mostra i metadati interni di Git. I due numeri sono gli hash abbreviati degli oggetti (blob) del file prima e dopo la modifica, e 100644 è la modalità del file (un file normale, non eseguibile).

index 6b0c6cf..b37e70a 100644

Simboli per le modifiche

Queste righe assegnano un simbolo a ciascuna sorgente di input del diff. Le righe di a/test.txt (l'originale) sono contrassegnate con ---, e le righe di b/test.txt (la nuova versione) sono contrassegnate con +++.

--- a/test.txt
+++ b/test.txt

Chunk del diff

Un diff non mostra l'intero file — solo le regioni modificate. Ogni tale regione è chiamata chunk (o hunk). I chunk includono alcune righe invariate di contesto circostante per permetterti di vedere dove si trova la modifica.

@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

La prima riga è l'intestazione del chunk, racchiusa nei simboli @@. Riassume gli intervalli di righe coinvolti: -1 significa "a partire dalla riga 1 del vecchio file" e +1 significa "a partire dalla riga 1 del nuovo file". Sotto l'intestazione, un - iniziale contrassegna una riga rimossa e un + iniziale contrassegna una riga aggiunta. Una riga modificata appare quindi come una rimozione seguita da un'aggiunta.

Flag comuni

Git offre diversi flag utili per diversi flussi di lavoro:

  • --staged (o --cached): Confronta le modifiche in stage nell'indice con il commit HEAD — ciò che un git commit registrerebbe.
  • --stat: Mostra un riepilogo condensato dei file modificati (inserimenti/eliminazioni per file) invece del diff completo.
  • --name-only: Restituisce solo i nomi dei file modificati.
  • --name-status: Come --name-only, ma aggiunge a ogni file la lettera di stato (M modificato, A aggiunto, D eliminato).
  • -w (o --ignore-all-space): Ignora le modifiche che riguardano solo gli spazi bianchi, utile quando la reindentazione nasconde le vere modifiche.

Ad esempio, per ottenere una panoramica rapida di quanto è cambiato ogni file:

git diff --stat
# test.txt | 2 +-
# 1 file changed, 1 insertion(+), 1 deletion(-)

Evidenziare le modifiche

Per le modifiche a livello di riga, l'output predefinito può essere rumoroso, perché Git mostra un'intera riga rimossa e un'intera riga aggiunta anche quando differisce solo una parola. I due strumenti seguenti evidenziano le parti esatte che sono cambiate.

git diff --color-words

Il primo modo è una modalità speciale integrata in git diff: --color-words. Suddivide le righe aggiunte e rimosse in token separati da spazi bianchi e poi calcola le differenze tra questi token, in modo che solo le parole modificate vengano colorate invece dell'intera riga.

git diff --color-words
diff --git a/test.txt b/test.txt
index 6b0c6cf..b37e70a 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

(Nota: --color-words evidenzia le modifiche inline usando i colori del terminale. In testo normale, il formato dell'output corrisponde al diff standard.)

git diff-highlight

Quando cloni il codice sorgente di Git, viene inclusa una sottodirectory chiamata contrib. Contiene strumenti correlati a Git, uno dei quali è diff-highlight. Evidenzia le parti modificate a livello di sotto-parola, andando più nel dettaglio rispetto a --color-words. Nota che questo strumento filtra lo standard input (vi si passa un diff tramite pipe) e richiede la colorazione del terminale per essere visibile.

git diff | git diff-highlight
diff --git a/test.txt b/test.txt
index 6b0c6cf..b37e70a 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Confrontare file binari

git diff può essere eseguito non solo su file di testo, ma anche su file binari. Per impostazione predefinita il risultato non è molto utile — Git ti dice solo che il file è cambiato, non come:

git diff
# Binary files a/script.pdf and b/script.pdf differ

Git dispone di una funzionalità che ti permette di specificare un comando shell per convertire il contenuto del file binario in testo prima di eseguire il diff. È necessaria una piccola configurazione. Prima di tutto, definisci un filtro textconv che descriva come convertire un determinato tipo binario in testo. Ad esempio, l'utility pdftohtml (disponibile tramite Homebrew) può trasformare un PDF in HTML. Ci sono due posti in cui configurare questo: per repository in .git/config, oppure globalmente in ~/.gitconfig.

[diff "pdfconv"]
textconv=pdftohtml -stdout

Poi collega uno o più pattern di file al filtro pdfconv creando un file .gitattributes nella root del repository:

*.pdf diff=pdfconv

Dopo questa configurazione, git diff esegue prima ogni file binario corrispondente attraverso il convertitore e calcola le differenze sull'output testuale del convertitore. Usando la stessa tecnica puoi ottenere diff leggibili da molti formati binari (zip, jar e altri archivi).

Confrontare un singolo file

git diff accetta anche un percorso di file esplicito. Quando viene passato un percorso, l'operazione è limitata a quel singolo file. Nell'esempio seguente, l'argomento ./path/to/file confronta le modifiche nella working directory con il commit HEAD:

git diff HEAD ./path/to/file

Confrontare tutte le modifiche

Per confrontare le modifiche nell'intero repository, esegui git diff senza un percorso di file. Ognuna delle forme sopra può essere invocata senza l'argomento ./path/to/file per applicare lo stesso confronto a ogni file nel repository locale.

Modifiche dall'ultimo commit

Un git diff senza argomenti confronta la working directory con la staging area (indice), quindi mostra solo le modifiche non in stage. Per vedere tutte le modifiche non committate dall'ultimo commit — sia in stage che non — confronta con HEAD:

git diff HEAD

Confrontare due commit

git diff accetta riferimenti Git, come nomi di branch, tag e hash di commit. Ogni commit ha un ID univoco, che puoi trovare con git log. Passa due ID di commit per confrontarli direttamente:

git diff <commit-hash-1> <commit-hash-2>

L'output mostra cosa è cambiato andando dal primo commit al secondo.

Confrontare branch

Confrontare branch funziona come qualsiasi altro input di riferimento per git diff. Ci sono due operatori da conoscere.

L'operatore a due punti confronta le punte di entrambi i branch:

git diff branch1..branch2

Si ottiene lo stesso risultato se i punti vengono omessi e si usa uno spazio tra i nomi dei branch. Esiste anche un operatore a tre punti:

git diff branch1...branch2

L'operatore a tre punti effettua il confronto sulla storia condivisa: sostituisce branch1 con l'antenato comune (merge base) dei due branch, mentre il secondo input rimane la punta di branch2. In altre parole, branch1...branch2 risponde alla domanda "cosa è successo su branch2 da quando ha divergito da branch1", che è solitamente quello che si vuole quando si esamina un feature branch prima di un git merge.

Confrontare un file tra due branch

Per confrontare un file specifico tra branch, passa il percorso del file come terzo argomento:

git diff master new_branch ./test.txt

Comandi correlati

  • git status — vedi quali file sono cambiati prima di usare git diff per vedere cosa è cambiato in essi.
  • git add — una volta che un diff sembra corretto, mettilo in stage; poi usa git diff --staged per rivedere cosa è in stage.
  • git commit — registra le modifiche in stage.
  • git log — trova gli hash dei commit da passare a git diff <commit> <commit>.
  • git show — visualizza il diff introdotto da un singolo commit.

Pratica

Pratica
Quali sono le funzionalità e le opzioni del comando 'git diff'?
Quali sono le funzionalità e le opzioni del comando 'git diff'?
Was this page helpful?