Una guida per annullare gli errori con Git (Parte 2)
Pubblicato: 2022-03-10In questa seconda parte della nostra serie su "Undoing Mistakes with Git", guarderemo di nuovo coraggiosamente il pericolo negli occhi: ho preparato quattro nuovi scenari apocalittici, inclusi, ovviamente, alcuni modi intelligenti per salvarci il collo! Ma prima di immergerci: dai un'occhiata ai precedenti articoli su Git per ulteriori metodi di autosoccorso che ti aiutano a annullare i tuoi errori con Git!
Andiamo!
Recupero di un ramo cancellato utilizzando il Reflog
Ti è mai capitato di cancellare un ramo e, poco dopo, ti sei reso conto che non avresti dovuto? Nell'improbabile eventualità che tu non conosca questa sensazione, posso dirti che non è una bella sensazione. Un misto di tristezza e rabbia si insinua su di te, mentre pensi a tutto il duro lavoro che è stato dedicato ai commit di quel ramo, a tutto il prezioso codice che ora hai perso.
Fortunatamente, c'è un modo per riportare indietro quel ramo dalla morte, con l'aiuto di uno strumento Git chiamato "Reflog". Abbiamo usato questo strumento nella prima parte della nostra serie, ma ecco un piccolo aggiornamento: Reflog è come un diario in cui Git annota ogni movimento del puntatore HEAD nel tuo repository locale. In altre parole meno nerd: ogni volta che esegui il checkout, il commit, l'unione, il rebase, il cherry-pick e così via, viene creata una voce di diario. Questo rende il Reflog una rete di sicurezza perfetta quando le cose vanno male!
Diamo un'occhiata a un esempio concreto:
$ git branch * feature/login master
Possiamo vedere che al momento abbiamo verificato la nostra feature/login
al ramo. Diciamo che questo è il ramo che cancelleremo (inavvertitamente). Prima di poterlo fare, tuttavia, dobbiamo passare a un ramo diverso perché non possiamo eliminare il nostro ramo HEAD corrente!
$ git checkout master $ git branch -d feature/login
Il nostro prezioso ramo di funzionalità ora è andato - e ti darò un minuto per (a) capire la gravità del nostro errore e (b) per piangere un po'. Dopo che avrai asciugato le lacrime, dobbiamo trovare un modo per riportare indietro questo ramo! Apriamo il Reflog (semplicemente digitando git reflog
) e vediamo cosa ha in serbo per noi:
Ecco alcuni commenti per aiutarti a dare un senso all'output:
- Prima di tutto, devi sapere che il Reflog ordina le sue voci in ordine cronologico: le voci più recenti sono in cima alla lista.
- L'elemento più in alto (e quindi il più recente) è il comando
git checkout
che abbiamo eseguito prima di eliminare il ramo. È registrato qui nel Reflog perché è uno di questi "movimenti del puntatore HEAD" che il Reflog registra così diligentemente. - Per annullare il nostro grave errore, possiamo semplicemente tornare allo stato precedente , che è anche registrato in modo pulito e chiaro nel Reflog!
Quindi proviamo questo, creando un nuovo ramo (con il nome del nostro ramo "perso") che inizia con questo hash SHA-1 dello stato "prima":
$ git branch feature/login 776f8ca
E voilà! Sarai felice di vedere che ora abbiamo ripristinato il nostro ramo apparentemente perduto!
Se stai usando una GUI desktop Git come "Tower", puoi prendere una bella scorciatoia: premi semplicemente CMD + Z sulla tastiera per annullare l'ultimo comando, anche se hai appena eliminato violentemente un ramo!
Spostamento di un commit in un ramo diverso
In molti team c'è un accordo per non impegnarsi su rami di lunga durata come main
o develop
: rami come questi dovrebbero ricevere nuovi commit solo attraverso integrazioni (ad esempio unioni o rebase). Eppure, certo, gli errori sono inevitabili: a volte dimentichiamo e ci impegniamo comunque su questi rami! Quindi, come possiamo ripulire il pasticcio che abbiamo creato?
Fortunatamente, questi tipi di problemi possono essere facilmente corretti. Rimbocchiamoci le maniche e mettiamoci al lavoro.
Il primo passo è passare al ramo di destinazione corretto e quindi spostare il commit utilizzando il comando cherry-pick
:
$ git checkout feature/login $ git cherry-pick 776f8caf
Ora avrai il commit sul ramo desiderato, dove avrebbe dovuto essere in primo luogo. Stupendo!
Ma c'è ancora una cosa da fare: dobbiamo ripulire il ramo dove è caduto accidentalmente all'inizio! Il comando cherry-pick
, per così dire, ha creato una copia del commit, ma l'originale è ancora presente sul nostro ramo di lunga data:
Ciò significa che dobbiamo tornare al nostro ramo di lunga data e utilizzare git reset
per rimuoverlo:
$ git checkout main $ git reset --hard HEAD~1
Come puoi vedere, stiamo usando il comando git reset
qui per cancellare il commit errato. Il parametro HEAD~1
dice a Git di "tornare indietro di 1 revisione dietro HEAD", cancellando efficacemente il commit più alto (e nel nostro caso: indesiderato) dalla cronologia di quel ramo.
E voilà: il commit è ora dove avrebbe dovuto essere in primo luogo e il nostro ramo di lunga data è pulito, come se il nostro errore non fosse mai accaduto!
Modifica del messaggio di un vecchio commit
È fin troppo facile contrabbandare un errore di battitura in un messaggio di commit e scoprirlo solo molto più tardi. In tal caso, la buona vecchia opzione --amend
di git commit
non può essere utilizzata per risolvere questo problema, perché funziona solo per l'ultimo commit. Per correggere qualsiasi commit più vecchio di quello, dobbiamo ricorrere a uno strumento Git chiamato "Interactive Rebase".
Innanzitutto, dobbiamo dire a Interactive Rebase quale parte della cronologia dei commit vogliamo modificare. Questo viene fatto alimentandolo con un hash di commit: il commit genitore di quello che vogliamo manipolare.
$ git rebase -i 6bcf266b
Si aprirà quindi una finestra dell'editor. Contiene un elenco di tutti i commit dopo quello che abbiamo fornito come base per Interactive Rebase nel comando:
Qui, è importante che tu non segua il tuo primo impulso: in questo passaggio, non modifichiamo ancora il messaggio di commit. Invece, diciamo a Git solo che tipo di manipolazione vogliamo fare con quale(i) commit. Abbastanza convenientemente, c'è un elenco di parole chiave di azione annotate nei commenti nella parte inferiore di questa finestra. Nel nostro caso, contrassegniamo la riga n. 1 con reword
(sostituendo così lo standard pick
).
Tutto ciò che resta da fare in questo passaggio è salvare e chiudere la finestra dell'editor. In cambio, si aprirà una nuova finestra dell'editor che contiene il messaggio corrente del commit che abbiamo contrassegnato. E ora è finalmente il momento di apportare le nostre modifiche!
Ecco l'intero processo a colpo d'occhio per te:
Correzione di un impegno interrotto (in modo molto elegante)
Infine, daremo un'occhiata a fixup
, il coltellino svizzero degli strumenti di annullamento. In parole povere, ti consente di correggere un commit interrotto/incompleto/errato dopo il fatto. È davvero uno strumento meraviglioso per due motivi:
- Non importa quale sia il problema.
Potresti aver dimenticato di aggiungere un file, avresti dovuto eliminare qualcosa, apportare una modifica errata o semplicemente un errore di battitura.fixup
funziona in tutte queste situazioni! - È estremamente elegante.
La nostra reazione normale e istintiva a un bug in un commit è produrre un nuovo commit che risolva il problema. Questo modo di lavorare, per quanto intuitivo possa sembrare, rende la cronologia dei commit molto caotica, molto presto. Hai commit "originali" e poi questi piccoli commit "bandaid" che risolvono le cose che sono andate storte nei commit originali. La tua storia è disseminata di piccoli e insignificanti impegni di cerotto che rendono difficile capire cosa è successo nella tua base di codice.
È qui che entra in gioco la fixup
. Ti consente ancora di eseguire questo commit di correzione del cerotto. Ma ecco che arriva la magia: quindi lo applica al commit originale, rotto (riparandolo in questo modo) e quindi scarta completamente il brutto commit del cerotto!
Possiamo fare insieme un esempio pratico! Diciamo che il commit selezionato qui è rotto.
Diciamo anche che ho preparato delle modifiche in un file chiamato error.html
che risolverà il problema. Ecco il primo passo che dobbiamo fare:
$ git add error.html $ git commit --fixup 2b504bee
Stiamo creando un nuovo commit, ma stiamo dicendo a Git che questo è speciale: è una correzione per un vecchio commit con l'hash SHA-1 specificato ( 2b504bee
in questo caso).
Il secondo passaggio, ora, è avviare una sessione di Interactive Rebase, perché la fixup
appartiene al grande set di strumenti di Interactive Rebase.
$ git rebase -i --autosquash 0023cddd
Vale la pena spiegare due cose su questo comando. Innanzitutto, perché ho fornito 0023cddd
come hash di revisione qui? Perché dobbiamo iniziare la nostra sessione Interactive Rebase al commit genitore del nostro compagno rotto.
Secondo, a cosa serve l'opzione --autosquash
? Ci vuole molto lavoro dalle nostre spalle! Nella finestra dell'editor che ora si apre, tutto è già pronto per noi:
Grazie all'opzione --autosquash
, Git ha già fatto il lavoro pesante per noi:
- Ha contrassegnato il nostro piccolo impegno di cerotto con la parola chiave azione di
fixup
. In questo modo, Git lo combinerà con il commit direttamente sopra e quindi lo scarterà. - Ha anche riordinato le righe di conseguenza, spostando il nostro commit cerotto direttamente sotto il commit che vogliamo correggere (di nuovo: la
fixup
funziona combinando il commit contrassegnato con quello sopra !).
Insomma: per noi non c'è altro da fare che chiudere la finestra!
Diamo un'ultima occhiata al risultato finale.
- Il commit precedentemente interrotto è stato corretto: ora contiene le modifiche che abbiamo preparato nel nostro commit band-aid.
- Il brutto commit stesso è stato scartato: la cronologia dei commit è pulita e facile da leggere, come se non si fosse verificato alcun errore.
Sapere come annullare gli errori è un superpotere
Congratulazioni! Ora puoi salvarti il collo in molte situazioni difficili! Non possiamo davvero evitare queste situazioni: non importa quanto siamo esperti come sviluppatori, gli errori fanno semplicemente parte del lavoro. Ma ora che sai come affrontarli, puoi affrontarli con una frequenza cardiaca rilassata.
Se vuoi saperne di più sull'annullamento degli errori con Git, posso consigliarti il "Kit di pronto soccorso per Git" gratuito, una serie di brevi video su esattamente questo argomento.
Divertiti a commettere errori e, naturalmente, a annullarli con facilità!