Modulo 10 — Annullare modifiche & time traveling
git checkout è il coltellino svizzero di Git: crea branch, switcha, ripristina file, annulla la history. È così “sovraccarico” che sono nati git switch e git restore per separarne gli usi.
Vedere un vecchio commit
Section titled “Vedere un vecchio commit”git checkout <hash> # bastano le prime ~7 cifre, vedi con git logAppare l’avviso del detached HEAD — non spaventarti, non è un errore.
Come funziona HEAD
Section titled “Come funziona HEAD”- Normalmente:
HEAD→ branch reference (es.master) → ultimo commit del branch. - Quando committi, il branch reference avanza; HEAD non si muove (punta al branch).
- Quando switchi branch, HEAD passa a puntare al nuovo branch reference.
Detached HEAD
Section titled “Detached HEAD”Quando fai checkout di un commit specifico, HEAD punta direttamente a quel commit, senza passare dal branch: sei “staccato”.
987fac... d8194d6 171615... ▲ HEAD Master ▲ (ora solo commit, non branch)Hai tre opzioni:
- Restare ed esplorare: guardare i file, fare esperimenti.
- Tornare dove eri, ri-attaccando HEAD:
git switch master - Creare un branch da qui e lavorarci:
git switch -c newbranch— HEAD torna a puntare a un branch e puoi fare commit normalmente. È il vero “time travel”: torni a un vecchio commit e fai partire una nuova linea da lì.
Riferimenti relativi: HEAD~n
Section titled “Riferimenti relativi: HEAD~n”git checkout HEAD~1 # il commit prima di HEAD (il genitore)git checkout HEAD~2 # due commit prima (il nonno)git checkout HEAD~3 # ...Scartare le modifiche di un file
Section titled “Scartare le modifiche di un file”Se hai modificato un file ma non vuoi tenerlo, riportalo allo stato dell’ultimo commit:
git checkout HEAD <file> # forma completagit checkout -- <file> # forma abbreviata⚠️ Le modifiche non committate vanno perse.
git restore — il comando moderno
Section titled “git restore — il comando moderno”Introdotto insieme a git switch per togliere compiti a checkout (che troppi sviluppatori trovavano confuso). Non è ancora citato da tutorial e libri vecchi, ma conviene conoscerlo.
git restore <file> # riporta il file allo stato di HEADgit restore --source HEAD~1 app.js # allo stato di un commit precedente # (o di un hash specifico)git restore --staged app.js # toglie il file dalla staging area # (hai fatto git add per sbaglio?)E se ti confondi: git status ti ricorda i comandi da usare.
git reset — annullare commit
Section titled “git reset — annullare commit”git reset <hash> # i commit successivi a <hash> spariscono dalla historygit reset --hard HEAD~1 # idem, e cancella ANCHE le modifiche nei filegit reset <hash>: sposta indietro il puntatore del branch; le modifiche restano nei file (potrai committarle di nuovo altrove, es. sul branch giusto).git reset --hard <commit>: cancella commit e modifiche ai file.
git revert — annullare con un nuovo commit
Section titled “git revert — annullare con un nuovo commit”git revert <hash>A differenza di reset, revert non riscrive la history: crea un nuovo commit che inverte le modifiche del commit indicato (ti verrà chiesto un messaggio). La vecchia storia resta intatta, con in più il commit “annulla”.
Reset o revert? La regola della collaborazione
Section titled “Reset o revert? La regola della collaborazione”- Commits mai condivisi (solo sul tuo machine): usa
reset— nessuno se ne accorgerà mai. - Commits già condivisi (es. pushati su GitHub, che altri hanno in locale): usa
revert.
Se fai reset su commit che il team ha già: hai alterato una history che gli altri possiedono — per loro è un incubo riconciliare le due versioni divergenti. Con revert, invece, i colleghi mergiano il nuovo commit “annulla” senza problemi: la history non è stata toccata.