git revert
Scopri il comando git revert, le differenze con git reset, le opzioni disponibili e gli esempi di utilizzo pratici.

Questa pagina illustra cosa fa git revert, le opzioni che accetta, un esempio completo, come si differenzia da git reset, come annullare un commit di merge e come risolvere i conflitti che un revert può generare.
Descrizione
Il comando git revert è un'operazione di annullamento che avanza in avanti. A differenza di comandi come git reset, non riscrive la cronologia. Invece di eliminare o spostare i commit, calcola l'inverso delle modifiche introdotte da un commit target e registra quell'inverso come un nuovo commit in cima al branch corrente.
Poiché dalla cronologia non viene rimosso nulla, git revert è il modo sicuro per annullare lavoro già pubblicato in un repository condiviso: tutti coloro che hanno il commit originale lo conservano, e il revert aggiunge semplicemente un commit successivo che lo annulla. Questo preserva l'intera cronologia delle revisioni, fondamentale per la tracciabilità e per una collaborazione pulita.
Alcune cose da tenere a mente:
- Un revert richiede un riferimento a un commit per sapere cosa annullare. Eseguire
git revertsenza argomenti produce un errore. - Un revert lascia l'albero di lavoro nello stato in cui si troverebbe se quel commit non fosse mai avvenuto (rispetto ai commit circostanti) — non necessariamente un diff vuoto, perché i commit successivi potrebbero ancora toccare le stesse righe.
- Annullare un revert riapplica la modifica originale, poiché l'inverso di un inverso è l'originale.
Quando usare git revert
Ricorri a git revert quando:
- Il commit che vuoi annullare è già stato pubblicato (inviato con push, aperto in una pull request o scaricato dai colleghi).
- Vuoi annullare un singolo commit specifico da qualche parte nella cronologia senza toccare i commit che sono venuti dopo.
- Hai bisogno di una registrazione verificabile che una modifica sia stata deliberatamente invertita.
Preferisci git reset quando il commit è locale e non pubblicato e vuoi semplicemente eliminarlo, oppure git commit --amend quando devi solo correggere il commit più recente (non ancora inviato).
Opzioni
-e --edit | Apre l'editor di sistema configurato e ti chiede di modificare il messaggio del commit prima di registrare il revert. Opzione predefinita. |
|---|---|
--no-edit | Impedisce al revert di aprire l'editor (il contrario dell'opzione -e). |
-n --no-commit | Aggiunge le modifiche inverse allo Staging Index e alla Working Directory invece di creare un nuovo commit. |
-m <parent-number> | Per annullare i commit di merge, specifica il commit genitore verso cui eseguire il revert. |
Esempi
# Stage the reverted changes without committing them (useful for review)
git revert -n HEAD
# Revert a merge commit against its first parent
git revert -m 1 <merge-commit-hash>Come funziona
Come git checkout e git reset, anche git revert accetta un commit specificato, ma non sposta i puntatori di riferimento su di esso. L'operazione di revert prende il commit specificato, inverte le modifiche di quel commit e crea un nuovo commit di revert.
Ecco un esempio di creazione di un repository:
Comando git revert
mkdir git_revert_example
cd git_revert_example/
git init .
#Initialized empty Git repository in /git_revert_example/.git/
touch w3docs_file
git add w3docs_file
git commit -m "original commit"
#[master (root-commit) 299b15f] original commit
#1 file changed, 0 insertions(+), 0 deletions(-)
#create mode 100644 w3docs_file
echo "original content" >> w3docs_file
git commit -m "add new content to w3docs_file"
#[master 3602d88] add new content to w3docs_file
#1 file changed, 1 insertion(+)
echo "prepended line content" >> w3docs_file
git commit -m "prepend content to w3docs file"
#[master 86bb32e] prepend content to w3docs file
#1 file changed, 1 insertion(+)
git log --oneline
#86bb32e prepend content to w3docs file
#3602d88 add new content to w3docs file
#299b15f original commitIn questo esempio, viene inizializzato un repository in una directory appena creata chiamata git_revert_example. Al repository vengono effettuati 3 commit in cui viene aggiunto un file chiamato w3docs_file, il cui contenuto è stato modificato due volte. Usiamo git log alla fine della configurazione del repository per mostrare tutti e 3 i commit nella cronologia. Ora possiamo invocare git revert:
git revert
git revert HEAD
#[master b9cd081] Revert "prepend content to w3docs file"
#1 file changed, 1 deletion(-)git revert non funziona senza passare un riferimento a un commit. Nell'esempio precedente abbiamo passato il riferimento HEAD per annullare l'ultimo commit. Un revert crea un nuovo commit e apre l'editor di sistema configurato affinché tu possa modificarne il messaggio (passa --no-edit per accettare quello predefinito). Possiamo usare git log e vedere il nuovo commit aggiunto in cima alla cronologia precedente:
git log --oneline
git log --oneline
#b9cd081 Revert "prepend content to w3docs file"
#86bb32e prepend content to w3docs file
#3602d88 add new content to w3docs_file
#299b15f original commitDopo il revert, il commit "prepend" (86bb32e) è ancora nella cronologia del progetto. git revert ha aggiunto un nuovo commit (b9cd081) che annulla le sue modifiche invece di eliminarlo. Questa è la differenza fondamentale rispetto a git reset.
Annullare senza committare
Passa -n (--no-commit) quando vuoi annullare più commit in un unico revert combinato, oppure ispezionare le modifiche inverse prima di registrarle. Git mette in stage le modifiche inverse ma si ferma prima di creare un commit, lasciandoti il controllo:
# Stage the inverse of the last two commits, then commit once
git revert -n HEAD~1 HEAD
git status # review the staged changes
git commit -m "Roll back the last two changes"Quando elenci più di un commit (o un intervallo), Git applica un revert per ciascuno. Senza -n creerebbe un commit per ogni revert; con -n vengono combinati nel singolo commit che crei tu stesso.
Annullare un commit di merge
Un commit di merge ha due genitori, quindi Git non può determinare da solo quale lato vuoi mantenere. Devi indicare quale genitore rappresenta la "linea principale" verso cui tornare usando -m <parent-number>. I numeri dei genitori iniziano da 1:
# Undo a merge, keeping the first parent (usually the branch you merged into)
git revert -m 1 <merge-commit-hash>In uno scenario tipico "merge di un branch di funzionalità in main", il genitore 1 è main e il genitore 2 è il branch di funzionalità, quindi -m 1 scarta le modifiche del branch di funzionalità.
Annullare un merge registra che i commit uniti sono stati disfatti. Se in seguito provi a fare il merge di quel branch di nuovo, Git vedrà quei commit come già uniti e li salterà. Per reintrodurre il lavoro di solito devi prima annullare il revert. Quando possibile, preferisci annullare i singoli commit piuttosto che annullare un merge.
Risolvere un conflitto di revert
Se i commit successivi hanno modificato le stesse righe che il revert sta cercando di annullare, Git si ferma con un conflitto — proprio come un conflitto di merge. Modifica i file contrassegnati, mettili in stage, quindi completa il revert in corso:
git revert HEAD~2
# CONFLICT (content): Merge conflict in w3docs_file
# error: could not revert 4f2a1c0... change w3docs_file
# resolve the conflict markers in the file, then:
git add w3docs_file
git revert --continue # records the revert commit
# Or, to back out of the whole operation:
git revert --abortReset vs. revert
Il comando git revert annulla un commit aggiungendo un nuovo commit, mentre git reset riscrive la cronologia spostando il puntatore del branch indietro e scartando i commit successivi.


Il revert è la scelta sicura per i commit già pubblicati in un repository condiviso e ti permette di puntare a un commit specifico ovunque nella cronologia. Evita git revert su commit privati e non pubblicati, dove git reset è più semplice e pulito.
Comandi correlati
- git reset — sposta il puntatore del branch e scarta i commit successivi (annullamento con riscrittura della cronologia).
- git commit --amend — corregge il commit più recente non ancora inviato.
- git checkout — scarta le modifiche non committate nell'albero di lavoro.
- git cherry-pick — l'operazione opposta: applica le modifiche di un commit sul branch corrente.