Nella lezione precedente abbiamo visto come ripristinare un file non ancora in staging area e come rimuoverlo dalla staging area, ma se avessimo fatto una commit di troppo? Magari abbiamo voluto testare qualcosa e non è andato come speravamo e vogliamo tornare indietro? Ci sono diversi modi per farlo e li vediamo tutti in questa lezione.
Annullare le modifiche con checkout
Ecco di nuovo il nostro caro vecchio git checkout. Sappiamo che con questo comando possiamo navigare nella cronologia di git e ripristinare i file non ancora aggiunti alla staging area.
Quando andiamo indietro nella cronologia la nostra repo entra in stato detached HEAD, ciò significa che non stiamo più lavorando in una branch. Ogni nuova commit sarà orfana e quando torneremo in una branch (la repo ritorna nello stato attached HEAD) il garbage collector di Git cancellerà quanto fatto durante la nostra esplorazione in stato detached. Per evitare che il garbage collector elimini le nostre commit orfane, dobbiamo essere in una branch.
Ipotizziamo quindi di essere in una situazione tipo questa:
$ git log --online 180277c (HEAD -> main) Crazy edit 40ba560 Add new file a515b13 Add english 0f773b5 Add message
Vogliamo tornare alla commit 40ba560 e per farlo possiamo usare git checkout in questo modo:
$ git checkout 40ba5600
A questo punto siamo in stato detached, ma le modifiche pazze che abbiamo fatto non ci sono. Possiamo quindi creare una nuova branch sempre con git checkout:
$ git checkout -b nuova_branch_senza_crazy_edit
Questo comando creerà e ci sposterà nella branch nuova_branch_senza_crazy_edit facendoci uscire dallo stato detached HEAD e portandoci su una nuova linea del tempo (avendo creato una nuova branch). Qui la commit 180277c non esiste, ma attenzione questa strategia ha un bel problema, perché se la branch dalla quale abbiamo diverto era la master/main branch risolviamo poco, potremmo fare un merge, ma ci ritroveremo a risolvere dei conflitti, direi un po’ too much, considerando le altre strategie a disposizione. In ogni caso questa strategia ci ha permesso di vedere ancora una volta la gran versatilità di git checkout.
Annullare le modifiche con revert
Il comando git revert ci permette di tornare indietro ad una commit, ma non come siamo abituati con checkout, qui si torna indietro sul serio, ripristinando la repository al punto in cui desideriamo ritornare.
Ipotizziamo sempre questa situazione:
$ git log --oneline 180277c (HEAD -> main) Crazy edit 40ba560 Add new file a515b13 Add english 0f773b5 Add message
Avendo noi la necessità di tornare alla commit precedente possiamo usare il comando revert come segue:
$ git revert HEAD
Git creerà una nuova commit senza le modifiche apportate dall’ultima commit. La nostra cronologia si arricchirà di una nuova commit e quella con le modifiche pazzerelle rimarrà.
$ git log --oneline 839432a (HEAD -> main) Revert “Crazy edit” 180277c Crazy edit 40ba560 Add new file a515b13 Add english 0f773b5 Add message
A differenza della strategia con git checkout questa evita la creazione di nuove branch. L’obiettivo è stato raggiunto, ma potrebbe non bastare ancora. Se stai lavorando su una repository pubblica, magari vuoi eliminare completamente la commit 180277c, come? Con la terza strategia
Annullare le modifiche con reset
Un comando già visto in passato, ma che al posto di ripristinare i file in questo caso lo usiamo per tornare indietro modificando anche la cronologia di Git.
Supponiamo sempre la nostra situazione iniziale:
$ git log --oneline 180277c (HEAD -> main) Crazy edit 40ba560 Add new file a515b13 Add english 0f773b5 Add message
Per poter tornare indietro alla commit 40ba560 con git reset possiamo scrivere:
$ git reset --hard 40ba560 HEAD is now at 40ba560 Add new file
Fatto! Controlliamo la cronologia
$ git log --oneline 40ba560 (HEAD -> main) Add new file a515b13 Add english 0f773b5 Add message
La nostra commit 180277c è definitivamente scomparsa.
Attenzione però anche questa terza strategia ha degli svantaggi, in particolar modo se lavoriamo con delle repository remote. Qualora ci sincronizzassimo con la repository remota Git ci mostrerà un errore. Git, infatti, presume che la branch inviata sia aggiornata con quella remota, ma avendo rimosso una commit non lo è più. Se state lavorando su repository remote allora è il caso di optare per git revert.
Conclusioni
Abbiamo visto quindi quali sono le migliori strategie per poter annullare le modifiche salvate. Nella prossima lezione vediamo come spostare un file, perché non è semplice come sembra.