Il controllo del tag Git porta allo "stato HEAD distaccato"


166

Sto sviluppando uno script di distribuzione per il mio progetto git e ho appena iniziato a usare i tag. Ho aggiunto un nuovo tag chiamato v2.0:

git tag -a v2.0 -m "Launching version 2.0"

E ho inserito questo tag nel repository remoto

git push --tags

Quando provo a eseguire lo script di distribuzione e controllo il v2.0tag ricevo questo messaggio:

Sei nello stato "HEAD distaccato". Puoi guardarti intorno, apportare modifiche sperimentali e impegnarle e puoi scartare qualsiasi commit che fai in questo stato senza influire su alcun ramo eseguendo un altro checkout. Se si desidera creare un nuovo ramo per conservare i commit creati, è possibile farlo (ora o in seguito) usando nuovamente -b con il comando di checkout. Esempio: git checkout -b new_branch_name HEAD è ora su

È normale? Il repository è in un limbo perché se lo faccio:

git branch

Ottengo questo risultato:

* (no branch)
  master

Scusa se questo è ovvio ma non sono riuscito a capirlo.


Quando dici "esegui lo script di distribuzione e verifica la v2.0" il tuo codice appare come "git checkout v2.0"? Sto provando a rinnovare il mio script di rilascio e quando eseguo "git checkout v2.0" dalla mia macchina di produzione ottengo "errore: pathspec 'v2.0' non corrisponde ad alcun file noto a git." Anche se ho eseguito "git push origin --tags" sul mio computer locale prima di eseguire "git checkout v2.0" in produzione. Ho anche provato a eseguire "git pull --tags" e "git fetch --tags" in produzione prima di chiamare "git checkout v2.0" e non funziona neanche ... sto ancora ottenendo il errore. Qualche idea?
John Erck,

3
Stavo per eliminare il commento sopra, ma poi ho pensato che tenerlo su potesse aiutare qualcun altro. Stavo ottenendo l'errore perché avevo un TYPO nel nome del mio tag mentre stavo eseguendo "git checkout v2.0". Tuttavia, l'errore correlato all'errore di battitura è esattamente lo stesso errore che otterrai se esegui "git checkout v2.0" SENZA un errore di battitura PRIMA di eseguire "git fetch --tags". Quindi, alla fine, il mio problema è stato risolto eseguendo "git fetch --tags" PRIMA di eseguire, "git checkout v2.0" senza errori di battitura. Accidenti!
John Erck,

Bene, sì, devi fare prima il tetch --tags (o git fetch che tirerà tutto dal telecomando) in modo che git possa controllare il tag. Mi dispiace, ho appena visto il tuo commento oggi.
Khriz,

Risposte:


429

Ok, prima alcuni termini leggermente semplificati.

In git, un tag(come molte altre cose) è ciò che viene chiamato un albero . È un modo di fare riferimento a un punto nella storia del progetto. Treeishes può essere un tag, un commit, un identificatore di data, un identificatore ordinale o molte altre cose.

Ora a branchè proprio come un tag ma è mobile. Quando sei "su" un ramo e fai un commit, il ramo viene spostato sul nuovo commit che hai fatto, indicando la sua posizione corrente.

Il tuo HEADè puntatore a un ramo che è considerato "attuale". Di solito, quando si clona un repository, HEADverrà indicato il masterquale a sua volta indicherà un commit. Quando poi fai qualcosa del genere git checkout experimental, cambi il HEADpuntare al experimentalramo che potrebbe puntare a un diverso commit.

Ora la spiegazione.

Quando si esegue un git checkout v2.0, si passa a un commit non indicato da a branch. L' HEADora è "staccato" e non punta a un ramo. Se decidi di effettuare un commit ora (come puoi), non c'è alcun puntatore di succursale da aggiornare per tenere traccia di questo commit. Passare a un altro commit ti farà perdere questo nuovo commit che hai fatto. Ecco cosa ti dice il messaggio.

Di solito, quello che puoi fare è dire git checkout -b v2.0-fixes v2.0. Questo creerà un nuovo puntatore di ramo sul commit indicato dal treeish v2.0(un tag in questo caso) e quindi sposta il tuo HEADpunto su quello. Ora, se fai dei commit, sarà possibile seguirli (usando la v2.0-fixesfiliale) e potrai lavorare come faresti di solito. Non c'è niente di "sbagliato" in ciò che hai fatto, soprattutto se vuoi dare un'occhiata al v2.0codice. Se tuttavia, si desidera apportare eventuali modifiche lì che si desidera monitorare, è necessario un ramo.

Dovresti dedicare un po 'di tempo a comprendere l'intero modello DAG di Git. È sorprendentemente semplice e rende tutti i comandi abbastanza chiari.


Ok grazie, non ho bisogno di apportare modifiche al codice, quindi penso che sia ok. Non ho bisogno di creare un ramo. Molte grazie!
Khriz,

1
Mi sono perso la prima volta che ho guardato questa risposta, ma dopo aver letto la documentazione di ramificazione di Git: http://git-scm.com/book/en/Git-Branching-What-a-Branch- È stato molto più chiaro .
Mark Stiles,

3
Risposta fantastica, ma posso aggiungere riguardo a: "Tornare a un altro commit ti farà perdere questo nuovo commit che hai fatto." - Puoi ancora trovare il commit git reflog, che è un ottimo comando da sapere! A meno che non sia avvenuta la garbage collection, è apparentemente "impossibile" perdere un commit.
Dmitry Minkovsky,

I commit senza referenze possono essere persi da un'operazione di garbage collection.
Noufal Ibrahim,

1
L'URL è errato perché hanno cambiato il layout della pagina.
jcubic,

12

Sì, è normale Questo perché fai il checkout di un singolo commit, che non ha una testa. Soprattutto (prima o poi) non è il capo di alcun ramo.

Ma di solito non c'è nessun problema con quello stato. Puoi creare un nuovo ramo dal tag, se questo ti fa sentire più sicuro :)


1
Ok, lo terrò in questo modo ... la sicurezza è comunque sopravvalutata;)
Khriz

Come hai commentato nella risposta di Noufals (è la migliore, devo dire;)): Finché non cambi nulla, non c'è nulla di cui preoccuparti. Tuttavia, se supponi che puoi cambiare qualcosa, puoi semplicemente creare un ramo, perché sono economici in Git e puoi eliminarlo (e ricrearlo in seguito e così via).
KingCrunch
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.