Perché il mio repository Git è entrato in uno stato HEAD distaccato?


387

Ho finito con una testa staccata oggi, lo stesso problema descritto in: git push dice tutto aggiornato anche se ho cambiamenti locali

Per quanto ne so, non ho fatto nulla di straordinario, mi sono semplicemente impegnato e spinto dal mio repository locale.

Quindi come sono finito con un detached HEAD?


18
Il check-out di una filiale remota sembra il modo più comune per farlo accidentalmente; un altro modo comune è di verificare branch-name@{n}, l'ennesima posizione precedente di branch-name. Ma non importa quale, a un certo punto ci deve essere stato un git checkout <rev>. Se questo non suona un campanello, allora probabilmente hai fatto quello che Will ha menzionato: hai provato a fare git checkout <file>e sei riuscito a specificare una revisione per caso.
Cascabel,

3
Per annullare uno stato HEAD distaccato, vedi Correggere una testa staccata Git? .

Il mio repository è finito in questo stato quando si sono verificati conflitti durante il rebasing. Fortunatamente Git mi ha detto cosa fare quando ho corso git status:all conflicts fixed: run "git rebase --continue"
Paul,

2
Succede anche se si digita accidentalmente git checkout remotes/origin/my-branchinvece di git checkout my-brancho git checkout origin/my-branch.
Adam Libuša,

@adam Libusa, grazie ha funzionato per me. Qual è la differenza tra telecomandi git checkout / origin / my-branch e git checkout my-branch. Non è lo stesso? ma quello che hai detto ha funzionato per me. Per curiosità, chiedo.
karunakar bhogyari,

Risposte:


281

Qualsiasi checkout di un commit che non è il nome di uno dei tuoi rami ti farà ottenere un HEAD distaccato. Un SHA1 che rappresenta la punta di un ramo fornisce ancora una TESTA staccata. Solo una verifica di un nome di filiale locale evita quella modalità.

Vedi impegno con una TESTA staccata

Quando HEAD è staccato, il commit funziona normalmente, tranne per il fatto che nessun ramo con nome viene aggiornato. (Puoi pensarlo come un ramo anonimo.)

testo alternativo

Ad esempio, se fai il checkout di un "ramo remoto" senza prima rintracciarlo, puoi finire con un HEAD staccato.

Vedi git: cambia ramo senza staccare la testa


Con Git 2.23 (agosto 2019), non è più necessario utilizzare il comando confusogit checkout .

git switch può anche effettuare il checkout di un ramo e ottenere un distacco HEAD, tranne:

  • ha --detachun'opzione esplicita

Per verificare il commit HEAD~3per ispezione temporanea o esperimento senza creare una nuova filiale:

git switch --detach HEAD~3
HEAD is now at 9fc9555312 Merge branch 'cc/shared-index-permbits'
  • non può essere staccato per errore da un ramo di tracciamento remoto

Vedere:

C:\Users\vonc\arepo>git checkout origin/master
Note: switching to 'origin/master'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

Vs. usando il nuovo git switchcomando:

C:\Users\vonc\arepo>git switch origin/master
fatal: a branch is expected, got remote branch 'origin/master'

Se si desidera creare un nuovo ramo locale tenendo traccia di un ramo remoto:

git switch <branch> 

Se <branch>non viene trovato ma esiste un ramo di tracciamento esattamente in un telecomando (chiamalo <remote>) con un nome corrispondente, trattalo come equivalente

git switch -c <branch> --track <remote>/<branch>

Niente più errore!
Niente più TESTE staccate indesiderate!


12
Un altro modo in cui è possibile inserire lo stato principale separato è se si è nel mezzo di un rebase interattivo e si desidera modificare uno dei commit. Quando Git ti lascia al commit per la modifica, rimarrai in uno stato di testa separato fino al termine del rebase.

In questa guida visiva, c'è questa spiegazione: git commit files creates a new commit containing the contents of the latest commit, plus a snapshot of files taken from the working directory. Additionally, files are copied to the stage.cosa significa "file copiati sullo stage"? Pensavo che i file fossero impegnati, il che significa che lo stage è stato cancellato?
max

16
In effetti, otterrai un HEAD distaccato ogni volta che esegui il checkout di qualsiasi commit dal suo SHA1, indipendentemente dal fatto che si trovi sulla punta di un ramo; l'unico tipo di cosa che è possibile effettuare il checkout senza ottenere una HEAD distaccata è un nome di filiale. Ad esempio, anche se masterè nello ed489schema sopra, git checkout ed489ti darà una TESTA staccata, mentre git checkout masternon lo sarà.
musiphil,

8
"You can think of this as an anonymous branch":) Mi piace l'analogia
Adrien Be


118

L'ho riprodotto solo ora per caso:

  1. elenca i rami remoti

    git branch -r
          origin/Feature/f1234
          origin/master
    
  2. Voglio verificarne uno localmente, quindi taglio incolla:

    git checkout origin/Feature/f1234
    
  3. Presto! Stato HEAD distaccato

    You are in 'detached HEAD' state. [...])
    

Soluzione n. 1:

Non includere origin/nella parte anteriore delle specifiche della mia filiale al momento del check out:

git checkout Feature/f1234

Soluzione n. 2:

Aggiungi -bparametro che crea un ramo locale dal telecomando

git checkout -b origin/Feature/f1234 o

git checkout -b Feature/f1234 tornerà all'origine automaticamente


14
Questa è quasi un'ottima risposta, ma non riesce a spiegare perché sei entrato in uno stato di testa distaccato.
Oca,

5
Sono d'accordo ma fornisce la soluzione che stavo cercando. Grazie!!
Kilmazing

Ho visto in questa altra risposta che git checkout -b Feature/f1234<=> git branch Feature/f1234e git checkout Feature/f1234.
Armfoot,

1
per impostazione predefinita sembra in origine, quindi quando dai origin/branchname, cerca origin/origin/branchnamedi dire che il primo è il nome remoto che usi -b, in caso contrario crea un anonymousramo che è staccato. Allo stesso modo per il checkout da un altro telecomando dovresti menzionare il -bparametro altrimenti git non ha modo di sapere che proviene da un nuovo telecomando, cercherà origin/remote/branchname.
garg10may

Sei un santo!
Harvey Lin,

12

provare

git reflog 

questo ti dà una cronologia di come i tuoi HEAD e le diramazioni dei rami sono state spostate in passato.

per esempio :

88ea06b HEAD @ {0}: checkout: passaggio da SVILUPPO a telecomandi / origine / SomeNiceFeature e47bf80 HEAD @ {1}: pull origin SVILUPPO: avanzamento rapido

la parte superiore di questo elenco è una ragione per cui si potrebbe riscontrare uno stato TESTATA INDIPENDENTE ... verificando un ramo di tracciamento remoto.


7

Può succedere facilmente se si tenta di annullare le modifiche apportate ricontrollando i file e non ottenendo la sintassi corretta.

Puoi vedere l'output di git log: potresti incollare qui la coda del registro dall'ultimo commit riuscito e tutti potremmo vedere cosa hai fatto. Oppure potresti incollarlo e chiederlo in modo #gitcorretto su IRC freenode.


5

Può succedere se hai un tag uguale a un ramo.

Esempio: se "release / 0.1" è il nome del tag, allora

git checkout release/0.1

produce HEAD distaccato a "release / 0.1". Se ti aspetti che release / 0.1 sia un nome di ramo, ti confondi.


1
Sì. Ma come risolverlo? Come si effettua il checkout della filiale?
Martin

5

Detached HEAD significa che ciò che è attualmente estratto non è una filiale locale.

Alcuni scenari che si tradurranno in uno Detached HEADstato:

  • Se esegui il checkout di una filiale remota , ad esempio origin/master. Questo è un ramo di sola lettura. Pertanto, quando si crea un commit da origin/masteresso sarà libero-mobile , cioè non collegato a nessun ramo.

  • Se esegui il checkout di un tag specifico o esegui il commit . Quando esegui un nuovo commit da qui, sarà di nuovo flottante , cioè non collegato a nessun ramo. Si noti che quando un ramo viene estratto, i nuovi commit vengono sempre posizionati automaticamente in punta.

    Quando si desidera tornare indietro ed effettuare il checkout di un commit o tag specifico per iniziare a lavorare da lì, è possibile creare un nuovo ramo originato da quel commit e passare a esso da git checkout -b new_branch_name. Ciò impedirà lo Detached HEADstato poiché ora è stato estratto un ramo e non un commit.


3

Un semplice modo accidentale è fare git checkout headun errore di battitura HEAD.

Prova questo:

git init
touch Readme.md
git add Readme.md
git commit
git checkout head

che dà

Note: checking out 'head'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 9354043... Readme


@VonC: grazie per quel link. Sto preparando un allenamento Git e voglio anche sottolineare perché a volte è così confuso. Ho già molti esempi (come quelli checkout -bche sembrano checkout ma in realtà rami) ma un altro elenco è il benvenuto.
Thomas Weller,

2

L'altro modo per entrare in uno stato head distaccato git è provare a eseguire il commit in un ramo remoto. Qualcosa di simile a:

git fetch
git checkout origin/foo
vi bar
git commit -a -m 'changed bar'

Nota che se lo fai, qualsiasi ulteriore tentativo di checkout origine / pippo ti riporterà in uno stato di testa staccato!

La soluzione è creare il tuo ramo foo locale che tiene traccia dell'origine / foo, quindi facoltativamente spingere.

Questo probabilmente non ha nulla a che fare con il tuo problema originale, ma questa pagina è in cima ai risultati di Google per "git distaccato testa" e questo scenario è gravemente sotto documentato.


Questa situazione sembra essere quella di cui parla la risposta di Owen sopra - dove tagliare e incollare "origine / foo" fa pensare a git come "origine / origine / foo".
mvanle,

1

Quando effettui il checkout a un commit git checkout <commit-hash>o a una filiale remota, HEAD si staccherà e proverà a crearne uno nuovo.

I commit che non sono raggiungibili da nessun ramo o tag verranno raccolti e rimossi dall'archivio dopo 30 giorni.

Un altro modo per risolverlo è creare un nuovo ramo per il commit appena creato e effettuare il checkout. git checkout -b <branch-name> <commit-hash>

Questo articolo illustra come arrivare allo stato HEAD distaccato .

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.