modulo 02 / lezione 10
Lavorare in solitario: i comandi quotidiani
git restore e git reset: tornare indietro in sicurezza
Distinguere le tre forme di 'annulla' di Git senza rompere niente di non recuperabile.
git restore e git reset: tornare indietro in sicurezza
Git offre molti modi per “tornare indietro”, ma non tutti fanno la stessa cosa. Alcuni toccano solo il working tree. Alcuni modificano l’index. Alcuni spostano HEAD. Alcuni possono cancellare lavoro non salvato.
La domanda corretta non è “come annullo?”. È: cosa voglio annullare, in quale area si trova, e il commit è già condiviso?
Perché questa lezione conta
Il panico con Git nasce spesso da un comando usato nel livello sbagliato. Hai staged un file per errore e usi reset --hard. Volevi rifare l’ultimo commit locale e fai revert. Volevi scartare una modifica non salvata e sposti HEAD.
Questa lezione costruisce una mappa decisionale per annullare senza distruggere.
Obiettivo operativo
Alla fine della lezione devi saper scegliere tra restore, restore --staged, reset --soft, reset --mixed, reset --hard e capire quando invece serve revert.
Scartare modifiche nel working tree
Se hai modificato un file ma non vuoi più quelle modifiche:
git restore src/file.ts
Questo riporta il file alla versione dell’index o di HEAD. Se le modifiche non erano salvate altrove, le perdi.
Prima controlla:
git diff src/file.ts
Regola: non usare restore su lavoro che non hai letto.
Togliere dallo stage
Se hai staged un file per errore:
git restore --staged src/file.ts
Il file resta modificato nel working tree, ma non sarà nel prossimo commit.
Questo è un comando sicuro nella maggior parte dei casi: non cancella il contenuto del file, sposta solo la modifica fuori dall’index.
git reset
reset sposta HEAD. Le opzioni decidono cosa succede a index e working tree.
git reset --soft HEAD~1
Sposta HEAD indietro di un commit, ma lascia index e working tree come erano. Utile se vuoi rifare l’ultimo commit mantenendo tutto staged.
git reset --mixed HEAD~1
Default. Sposta HEAD e aggiorna index, ma lascia i file modificati nel working tree. Utile se vuoi disfare un commit e rivedere lo staging.
git reset --hard HEAD~1
Sposta HEAD, index e working tree. Le modifiche non committate vengono scartate. È il comando da trattare come lama affilata.
Locale vs condiviso
Se il commit è solo locale, puoi riscrivere:
git reset --soft HEAD~1
Se il commit è già su un branch condiviso, preferisci:
git revert <sha>
revert crea un nuovo commit che annulla l’effetto del commit precedente, senza riscrivere la storia pubblica.
Scheda decisionale
Ho modifiche non staged da buttare -> git restore file
Ho staged un file per errore -> git restore --staged file
Ho fatto commit locale ma voglio rifarlo -> git reset --soft HEAD~1
Ho fatto commit locale e voglio ristagiare tutto -> git reset --mixed HEAD~1
Voglio cancellare tutto il lavoro locale -> git reset --hard
Ho pushato e devo annullare -> git revert
Prima dei comandi rischiosi
Prima di reset --hard:
git status -sb
git diff
git diff --staged
Se hai dubbi, crea un branch di salvataggio:
git branch backup-prima-reset
Oppure una patch:
git diff > /tmp/prima-reset.patch
Laboratorio guidato
In un repo demo simula cinque casi:
- modifica non staged da scartare;
- file staged per errore;
- ultimo commit da rifare mantenendo stage;
- ultimo commit da disfare mantenendo modifiche working;
- commit già pushato da annullare con revert.
Per ogni caso annota cosa succede a HEAD, index e working tree.
Output atteso
Una scheda personale “voglio X -> comando Y” con avvertenze:
Non uso reset --hard se non ho letto status e diff.
Non riscrivo commit già condivisi senza accordo.
Uso revert per storia pubblica.
Errori comuni
Usare reset per tutto. Spesso basta restore --staged.
Confondere revert e reset. Revert aggiunge storia, reset la sposta.
Fare hard reset su branch con lavoro non salvato. Se non hai commit, branch o patch, potresti perdere modifiche.
Riscrivere storia condivisa. Costringe gli altri a riparare il proprio clone.
Checklist di verifica
- so cosa cambia tra
restoreereset; - so cosa fanno
--soft,--mixed,--hard; - so quando usare
revert; - controllo status e diff prima dei comandi distruttivi;
- so creare un branch backup prima di rischiare.
Esercizi
Base · facile
Annulla una modifica non ancora in stage, riportando un file all’ultima versione committata.
Soluzione
git restore file.txt # scarta le modifiche non in stage del file
git restore riporta il file allo stato dell’ultimo commit, scartando le modifiche del working tree. Attenzione: il lavoro non committato e non in stage va perso, perché non era da nessuna parte salvato.
Intermedio · medio
Togli un file dallo stage senza perdere le modifiche, poi spiega la differenza tra git restore --staged e git restore.
Soluzione
git restore --staged file.txt # index → working tree (resta modificato, non più staged)
git restore file.txt # scarta del tutto la modifica nel working tree
git restore --staged tocca solo l’index: rimuove il file dallo stage ma conserva le modifiche su disco. git restore (senza --staged) tocca il working tree: butta via le modifiche. Il primo è reversibile (il lavoro c’è ancora), il secondo no.
Sfida · difficile
Spiega la differenza tra git reset --soft, --mixed e --hard spostando HEAD indietro di un commit. Indica quale è pericoloso e perché.
Soluzione
git reset --soft HEAD~1 # sposta HEAD; modifiche restano staged
git reset --mixed HEAD~1 # (default) HEAD indietro; modifiche tornano non-staged
git reset --hard HEAD~1 # HEAD indietro E cancella le modifiche dal working tree
Tutti spostano il branch indietro di un commit, ma cambiano cosa succede al lavoro: --soft lo lascia in stage (pronto da ricommittare), --mixed lo lascia nel working tree non in stage, --hard lo distrugge. --hard è il pericoloso: le modifiche non committate spariscono senza rete. Per i commit “persi” con reset resta comunque il reflog per recuperarli; per le modifiche non committate cancellate da --hard, no.
Collegamenti
- Modulo: Lavorare in solitario: i comandi quotidiani — lezione 10 del corso.
- Il reflog del modulo 4 aiuta quando qualcosa è già andato storto.