Come si risolve una “testa staccata” in un repository Git?

0
587

Uno dei normali messaggi di errore che potresti incontrare Git è l'avviso che “sei in ‘Head staccato’ stato.” Potresti esserti imbattuto accidentalmente in questo problema, ma non preoccuparti, è un problema normale e può essere facilmente risolto una volta capito cosa significa.

Cos'è Git HEAD?

“HEAD” è semplicemente un alias per il tuo attuale commit di lavoro, proprio come la tua directory corrente su una riga di comando. Qualunque sia lo stato in cui si trova il tuo repository Git, HEAD punta sempre a qualcosa e i nuovi commit verranno aggiunti davanti a HEAD.

Di solito, HEAD non fa riferimento direttamente a un singolo commit. Punta invece a un ramo e fa riferimento indirettamente all'ultimo commit in quel ramo. Ogni volta che “checkout” un nuovo ramo, Git passa l'HEAD a quel ramo. Questo ti permette di fare nuovi commit che verranno aggiunti alla fine di quel ramo.

Tuttavia, puoi anche controllare i singoli commit. E se volessi esaminare il repository in un momento specifico? Questo è uno dei maggiori vantaggi di Git, ma presenta un piccolo problema con il modo in cui Git struttura le cose. Dal momento che i nuovi commit non aggiorneranno un ramo, qualsiasi commit che fai dopo aver spostato l'HEAD verrà staccato da tutti i riferimenti del ramo, quindi, “Head staccato.

Questo può effettivamente essere abbastanza utile. Supponiamo che tu abbia spostato l'HEAD indietro di alcuni commit e quindi apportato alcuni aggiornamenti sperimentali. Fondamentalmente stai creando un nuovo ramo, che potrebbe essere unito a master in seguito.

Pubblicità

Dovrai integrarlo ufficialmente nel repository Git se decidi di mantenere le modifiche, ma come strumento per apportare modifiche a ritroso nel tempo, avere un HEAD staccato non è così spaventoso come sembra.

Se sei arrivato qui per caso

È molto facile finire qui per caso ed essere confuso dal messaggio di errore di cui Git si lamenta nonostante non abbia fatto nulla di sbagliato. Fortunatamente, è incredibilmente facile da risolvere:

Se hai appena estratto un commit e non hai toccato il repository altrimenti (non sono stati effettuati nuovi commit), puoi semplicemente spostare il TORNA al punto in cui appartiene con git checkout:

git checkout master

Questo è fondamentalmente come eseguire cd su Linux, tranne che Git associa ancora commit e modifiche nella cache con il vecchio HEAD, quindi non vuoi controllare se hai commit o modifiche che rimarrebbero in sospeso.

Se hai apportato alcune modifiche e vuoi semplicemente buttarle via, puoi eseguire un hard reset al master:

git reset –hard origin/master git clean -d –force

Se vuoi salva i tuoi commit però, dovrai unirli ufficialmente di nuovo nella timeline di Git.

Se vuoi salvare le tue modifiche

La prima cosa che vorrai fare se vuoi mantenere le modifiche che hai fatto mentre sei in uno stato HEAD staccato è creare un nuovo ramo. Questo perché il Garbage Collector di Git ripulirà automaticamente i commit distaccati, quindi non vorrai mai perderne traccia.

git branch destructed-branch Advertisement

Allora tu può controllare questo ramo per spostare l'HEAD in modo che non sia più scollegato e punta invece a questo nuovo ramo ufficiale:

git checkout staccato-branch

Una volta registrate le modifiche, hai una delle due opzioni. Questo nuovo ramo è fondamentalmente un normale ramo di funzionalità, quindi puoi sia git merge o git rebase.

L'unione è semplice; checkout master e unisci il ramo distaccato:

git checkout master git merge destructed-branch

Funziona bene se ti stai integrando in un ramo che necessita di approvazione, come nel caso delle richieste pull e del codice recensioni. Potrebbe essere necessario seguire il processo di approvazione del tuo team anziché eseguire personalmente questi comandi.

Se hai accesso, ad esempio se ti stai unendo di nuovo in un ramo di funzionalità su cui stai lavorando, un metodo migliore è quello di selezionare i commit scollegati. Cherry picking fondamentalmente copia un commit e lo incolla su un altro ramo. Di solito viene utilizzato per estrarre commit specifici da un ramo di funzionalità prima che tutto sia pronto, ma in questo caso, il cherry-picking può riconciliare il ramo staccato senza un'unione.

Pubblicità

In questo esempio, il commit sopra è scollegato. Invece di unirlo, è stato scelto con cura e spostato nel ramo delle funzionalità. Questo sposta HEAD e feature branch in modo che puntino all'ultimo commit senza un'unione. Quindi, il commit staccato originale può essere scartato.

Per prima cosa, devi creare il ramo staccato, e poi controllare il ramo della funzionalità per spostare lì l'HEAD:

git branch staccato -branch git checkout feature

Quindi esegui Git log per ottenere un elenco di commit:

git log –pretty=format:”%h %s” –graph

Quindi puoi selezionare un commit tramite il suo ID:

git cherry -pick 1da76d3

Quindi, una volta che hai confermato che i commit selezionati sono stati applicati correttamente, puoi eliminare il ramo staccato, poiché i commit sono stati copiati e non è più utilizzato.

git branch -D staccato-branch

Ribasare invece di unire

Potresti anche fare un rebase. I rebase sono diversi dai merge in quanto riscrivono la cronologia del ramo, sollevando i commit distaccati e spostandoli nella parte anteriore del ramo.

Tuttavia, il problema è che ti rimangono ancora due rami e dovrai comunque unire funzionalità e ramo distaccato insieme, lasciandoti con un commit di unione in entrambi i casi. Ma lascia il repository con una cronologia Git più lineare, che è preferibile eseguire git merge se hai l'autorità per farlo.