W3docs

Introduzione

Impara ad annullare modifiche e commit in Git con checkout, restore, reset, revert, clean e amend — con esempi chiari e quando usare ogni comando.

annullare le modifiche

A differenza della maggior parte degli editor, Git non ha un singolo pulsante "annulla". Fornisce invece un piccolo insieme di comandi, ognuno dei quali agisce in un'area diversa in cui vive il tuo lavoro: la working directory (i file su disco), lo staging index (le modifiche marcate per il prossimo commit) e la cronologia dei commit (snapshot già registrati). Scegliere il comando giusto dipende da quale di queste tre aree vuoi ripristinare e se la modifica è già stata condivisa con altri.

Questa pagina copre l'intero toolkit: esaminare la cronologia, ripristinare file e annullare uno o più commit — con git checkout, git restore, git reset, git revert, git clean e git commit --amend.

Scegliere il comando giusto

Prima di qualsiasi comando specifico, è utile sapere quale area tocca ciascuno e se riscrive la cronologia:

ObiettivoComandoSicuro da condividere?
Scartare le modifiche a un file tracciatogit restore <file> (o git checkout -- <file>)
Rimuovere un file dallo staginggit restore --staged <file> (o git reset HEAD <file>)
Eliminare file non tracciatigit clean
Correggere il commit più recentegit commit --amendsolo se non è stato fatto push
Spostare il branch a un commit precedentegit resetsolo in locale
Annullare un commit aggiungendo l'inversogit revert

La regola più importante: reset e amend riscrivono la cronologia, quindi usali solo su commit che non hai ancora fatto push. Per tutto ciò che è già condiviso, usa revert.

Esaminare i commit precedenti

Non puoi annullare ciò che non riesci a trovare. Lo strumento migliore per esaminare la cronologia è git log. Ogni commit ha un hash identificativo che usi per fare riferimento ad esso:

git log --oneline
a3b2a21 Crossword solver with Vue.js
c54ce02 New logic for crossword game
3acb8d0 Some changes in crossword logic
de32112 Styling crossword table area

Per impostazione predefinita, git log mostra solo i commit raggiungibili dal branch corrente. Per visualizzare i commit su tutti i branch, aggiungi --all. Usa git checkout o git switch per visitare altri branch.

Visualizzare una revisione precedente

Per ispezionare il progetto com'era in un punto precedente, trova prima l'hash della revisione desiderata:

git log --oneline
b7119f2 Changes in Scrabble Solver
234be24 Fixing search input bug
b235bf4 Make some changes to solver.php
256a81c Create solver.php
3243e12 Initial changes

Poi controlla quel commit tramite il suo hash:

git checkout b235bf4

Ora puoi navigare tra i file, eseguire test e persino modificare le cose. Nulla di ciò che fai qui viene registrato su un branch, quindi il tuo lavoro attuale è al sicuro. Questo stato temporaneo si chiama detached HEADHEAD punta direttamente a un commit invece che alla punta di un branch. Torna al tuo branch quando hai finito:

git switch -  # or: git checkout master

Una volta tornato sul tuo branch, usa git revert o git reset per annullare le modifiche desiderate.

Annullare uno snapshot committato

Esistono diversi modi per annullare un commit. Quello giusto dipende dal fatto che il commit sia già stato condiviso. Immagina che la nostra cronologia sia così:

git log --oneline
863fa8e Making some improvements
b235bf4 Make some changes to solver.php
256a81c Create solver.php
3243e12 Initial changes

Le sezioni seguenti annullano il commit 863fa8e Making some improvements in tre modi diversi.

Con git checkout (ispeziona senza modificare il branch)

Fare il checkout del commit precedente, b235bf4, mette il repository nello stato prima del commit con le migliorie:

git checkout b235bf4

Si tratta di una deviazione di sola lettura, non di un vero annullamento: si finisce in uno stato di HEAD distaccato (detached). Qualsiasi nuovo commit creato qui diventa orfano non appena si torna a un branch consolidato, e il garbage collector di Git potrebbe alla fine rimuoverlo. Per conservare il lavoro fatto da questo stato, crea un branch da qui:

git checkout -b improvements-removed

Ora hai un nuovo branch, improvements-removed, la cui cronologia non ha mai incluso 863fa8e. Il checkout è il metodo migliore per osservare uno stato precedente; i due comandi successivi invece annullano effettivamente il commit.

Con git revert (l'annullamento sicuro e condivisibile)

git revert HEAD crea un nuovo commit che applica l'inverso del commit target. Nulla viene cancellato — la cronologia cresce in avanti:

git revert HEAD

Dopo averlo eseguito, il log appare così:

git log --oneline
23a4b42 Revert "Making some improvements"
863fa8e Making some improvements
b235bf4 Make some changes to solver.php
256a81c Create solver.php
3243e12 Initial changes

L'effetto di 863fa8e è ora annullato, ma il commit è ancora nella cronologia; 23a4b42 ne inverte semplicemente le modifiche. Poiché nulla viene riscritto, si rimane sullo stesso branch senza mai interrompere il clone di altri. Questo è l'annullamento corretto per i commit che sono stati già sottoposti a push o condivisi pubblicamente.

Con git reset (riscrivi la cronologia locale)

git reset sposta il puntatore del branch corrente a un commit scelto. Eseguendo git reset --hard b235bf4 si riporta il branch a quel commit e si scartano tutte le modifiche successive:

git reset --hard b235bf4
git log --oneline
b235bf4 Make some changes to solver.php
256a81c Create solver.php
3243e12 Initial changes

Il commit 863fa8e è sparito dalla cronologia di questo branch. È un'operazione pulita e diretta, ma poiché riscrive la cronologia va usata solo su commit che non sono stati ancora sottoposti a push. git reset accetta un flag di modalità che controlla fino a dove si estende l'annullamento:

  • --soft — sposta solo il puntatore del branch; mantiene le modifiche nello staging.
  • --mixed (predefinito) — sposta il puntatore e rimuove le modifiche dallo staging, ma le mantiene nella working directory.
  • --hard — sposta il puntatore e scarta le modifiche sia dallo staging che dalla working directory.
Attenzione

git reset --hard scarta in modo permanente il lavoro non committato nella working directory. Non c'è alcuna fase di staging da cui recuperarlo. Usa --soft o --mixed quando vuoi solo rifare il commit ma mantenere le modifiche.

Annullare l'ultimo commit

A volte non vuoi rimuovere il commit più recente — hai semplicemente eseguito il commit troppo presto o hai scritto un messaggio poco chiaro. Aggiungi allo staging eventuali modifiche aggiuntive con git add, poi esegui l'amend:

git add forgotten-file.txt
git commit --amend

Git apre l'editor configurato in modo da poter modificare il messaggio dell'ultimo commit, e le nuove modifiche nello staging vengono incorporate nello stesso commit. Per cambiare solo il messaggio in una riga:

git commit --amend -m "A clearer message"

L'amend sostituisce il commit precedente con uno nuovo (con un nuovo hash), quindi trattalo come reset: esegui l'amend solo su commit che non hai ancora sottoposto a push.

Annullare le modifiche non committate

Prima che una modifica venga committata, si trova nella working directory e nello staging index, quindi puoi annullarla da entrambe le aree senza toccare la cronologia. Il comando moderno è git restore:

# Discard edits to a tracked file (working directory)
git restore <file>
# Unstage a file but keep its edits
git restore --staged <file>

I vecchi equivalenti funzionano ancora e compaiono in molta documentazione:

# Discard changes in the working directory
git checkout -- <file>
# Unstage a file
git reset HEAD <file>

Rimozione di file non tracciati

git restore e reset agiscono solo sui file che Git già conosce. Per eliminare file nuovi e non tracciati, usa git clean. Visualizza sempre un'anteprima prima con -n (dry run):

git clean -n      # list what would be removed
git clean -f      # actually remove untracked files

Come si relazionano le tre aree

Vale la pena tenere chiare le tre aree, perché ogni comando di annullamento ne colpisce una specifica:

  • Working directory — i file su disco che il tuo editor modifica. git restore <file> e git clean operano qui.
  • Staging index — lo snapshot che stai costruendo per il prossimo commit. git add vi inserisce le modifiche; git restore --staged (un reset --mixed) le respinge nella working directory.
  • Cronologia dei commit — snapshot registrati. git reset la riscrive; git revert vi aggiunge.

Recupero da un annullamento errato

Un reset o un branch eliminato possono sembrare terrificanti, ma Git raramente perde qualcosa immediatamente. Il git reflog registra dove puntava HEAD, così puoi trovare l'hash di un commit "perso" e fare il reset verso di esso:

git reflog
1a2b3c4 HEAD@{0}: reset: moving to b235bf4
863fa8e HEAD@{1}: commit: Making some improvements

Recupera con git reset --hard 863fa8e (oppure crea un branch da lì). Se vuoi solo mettere da parte temporaneamente il lavoro anziché annullarlo, considera git stash.

Annullare modifiche pubbliche

Una volta che un commit è stato sottoposto a push, altre persone potrebbero averlo. Usa git revert per le modifiche pubbliche, mai git reset. Reset rimuove i commit dalla cronologia, quindi riscrivere un branch condiviso costringe tutti gli altri a riparare i propri clone. Revert lascia il commit originale al suo posto e registra un nuovo commit che lo inverte — sicuro per chiunque abbia già fatto pull.

Esercitazione

Pratica
Quali sono le funzioni dei diversi comandi Git utilizzati per annullare modifiche e commit?
Quali sono le funzioni dei diversi comandi Git utilizzati per annullare modifiche e commit?
Was this page helpful?