Por que meu repositório Git entrou em um estado HEAD desanexado?

387

Acabei hoje com uma cabeça desanexada, o mesmo problema descrito em: git push diz tudo atualizado, mesmo que eu tenha alterações locais

Até onde eu sei, não fiz nada fora do comum, apenas comete e empurra meu repositório local.

Então, como eu acabei com um detached HEAD?

Adam Bergmark
fonte
18
Verificar uma ramificação remota parece ser a maneira mais comum de fazer isso acidentalmente; Outra maneira comum é verificar branch-name@{n}, a nona posição anterior de branch-name. Mas não importa o que, em algum momento deve ter havido um git checkout <rev>. Se isso não tocar, provavelmente você fez o que Will mencionou - tentou fazer git checkout <file>e conseguiu especificar uma revisão por acidente.
Cascabel
3
Para desfazer um estado HEAD desanexado, consulte Corrigir uma cabeça desanexada do Git? .
Meu repo terminou nesse estado quando foram encontrados conflitos durante o rebase. Felizmente, o Git me disse o que fazer quando eu corri git status:all conflicts fixed: run "git rebase --continue"
Paul
2
Também acontece se você digitar acidentalmente em git checkout remotes/origin/my-branchvez de git checkout my-branchou git checkout origin/my-branch.
Adam Libuša
@ Adam Libusa, Obrigado, funcionou para mim. Qual é a diferença entre controles remotos / origem / my-branch do git checkout e my-branch do git checkout. Não é o mesmo. mas o que você disse funcionou para mim. Por curiosidade, estou perguntando.
karunakar bhogyari 17/03

Respostas:

281

Qualquer verificação de uma confirmação que não seja o nome de uma de suas filiais, resultará em um HEAD desanexado. Um SHA1 que representa a ponta de um ramo ainda fornece uma CABEÇA desanexada. Somente uma verificação de um nome de filial local evita esse modo.

Veja confirmação com um HEAD desanexado

Quando HEAD é desanexado, confirma o trabalho normalmente, exceto que nenhuma ramificação nomeada é atualizada. (Você pode pensar nisso como um ramo anônimo.)

texto alternativo

Por exemplo, se você fizer check-out de uma "ramificação remota" sem rastrear primeiro, poderá terminar com um HEAD desanexado.

Veja git: switch branch sem destacar a cabeça


Com o Git 2.23 (agosto de 2019), você não precisa usar o comando confusogit checkout .

git switch também pode fazer checkout de uma filial e obter um HEAD desanexado, exceto:

  • tem uma --detachopção explícita

Para verificar o commit HEAD~3para inspeção temporária ou experimento sem criar uma nova ramificação:

git switch --detach HEAD~3
HEAD is now at 9fc9555312 Merge branch 'cc/shared-index-permbits'
  • ele não pode desanexar por engano um ramo de rastreamento remoto

Vejo:

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 o novo git switchcomando:

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

Se você deseja criar uma nova filial local, rastreando uma filial remota:

git switch <branch> 

Se <branch>não for encontrado, mas existir um ramo de rastreamento em exatamente um controle remoto (chame-o <remote>) com um nome correspondente, trate como equivalente a

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

Não há mais erro!
Não há mais CABEÇA destacada e indesejada!

VonC
fonte
12
Outra maneira de inserir o estado principal desanexado é se você estiver no meio de uma nova refazer interativa e desejar editar um dos commit. Quando o Git deixa você no commit para editar, você fica em um estado de cabeça desanexada até terminar a rebase.
Neste guia visual, há esta explicação: 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.O que significa "arquivos são copiados para o palco"? Eu pensei que os arquivos foram confirmados, o que significa que o palco está limpo?
máx
16
De fato, você receberá um HEAD desanexado sempre que fizer o checkout de qualquer commit pelo seu SHA1, esteja ele na ponta de um ramo; o único tipo de coisa que você pode fazer o checkout sem obter um HEAD desanexado é um nome de filial. Por exemplo, mesmo que masteresteja no ed489diagrama acima, git checkout ed489você receberá um HEAD desanexado, enquanto git checkout masternão.
Musiphil
8
"You can think of this as an anonymous branch":) Eu gosto da analogia
Adrien Seja
118

Reproduzi isso agora por acidente:

  1. lista as ramificações remotas

    git branch -r
          origin/Feature/f1234
          origin/master
    
  2. Quero fazer o checkout um localmente, então corto a pasta:

    git checkout origin/Feature/f1234
    
  3. Presto! Estado HEAD desanexado

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

Solução 1:

Não inclua origin/na parte da frente das especificações da minha filial ao fazer o check-out:

git checkout Feature/f1234

Solução 2:

Adicione -bparâmetro que cria uma filial local a partir do controle remoto

git checkout -b origin/Feature/f1234 ou

git checkout -b Feature/f1234 ele voltará à origem automaticamente

Owen
fonte
14
Essa é quase uma ótima resposta, mas falha ao explicar por que você entrou em um estado principal desanexado.
Goose
5
Concordo, mas fornece a solução que eu estava procurando. Obrigado!!
Kilmazing
Eu vi nessa outra resposta que git checkout -b Feature/f1234<=> git branch Feature/f1234e git checkout Feature/f1234.
Armfoot
11
Por padrão, ele parece na origem; portanto, quando você fornece origin/branchname, procura origin/origin/branchnamedizer que o primeiro é o nome remoto que você usa -b; caso contrário, ele cria um anonymousramo que é desanexado. Da mesma forma, para fazer o check-out de um controle remoto diferente, você teria que mencionar o -bparâmetro, caso contrário, o git não tem como saber que é de um novo controle remoto, ele procurará origin/remote/branchname.
precisa saber é o seguinte
Você é um santo!
Harvey Lin
12

tentar

git reflog 

isso fornece um histórico de como os ponteiros HEAD e ramo foram movidos no passado.

por exemplo :

88ea06b HEAD @ {0}: finalização da compra: movendo-se de DEVELOPMENT para controles remotos / origem / SomeNiceFeature e47bf80 HEAD @ {1}: pull origin DEVELOPMENT: Avanço rápido

o topo desta lista é um dos motivos em que se pode encontrar um estado DETACHED HEAD ... verificando um ramo de rastreamento remoto.

André R.
fonte
7

Isso pode acontecer facilmente se você tentar desfazer as alterações feitas ao verificar novamente os arquivos e não conseguir obter a sintaxe correta.

Você pode ver a saída de git log- você pode colar o final do log aqui desde a última confirmação bem-sucedida, e todos pudemos ver o que você fez. Ou você pode colocá-lo em uma lixeira e pedir muito bem no #gitIRC do freenode.

Vai
fonte
5

Isso pode acontecer se você tiver uma tag com o mesmo nome de um ramo.

Exemplo: se "release / 0.1" for o nome da tag,

git checkout release/0.1

produz HEAD desanexado em "release / 0.1". Se você espera que release / 0.1 seja um nome de filial, fica confuso.

Radzimir
fonte
11
Sim. Mas como você conserta isso? Como você faz um checkout da filial?
Martin
5

Detached HEAD significa que o que foi retirado no momento não é uma filial local.

Alguns cenários que resultarão em um Detached HEADestado:

  • Se você fizer check-out de uma filial remota , digamos origin/master. Este é um ramo somente leitura. Portanto, ao criar um commit a partir origin/masterdele, será flutuante , ou seja, não conectado a nenhum ramo.

  • Se você fizer o checkout de uma tag específica ou confirmar . Ao fazer um novo commit a partir daqui, ele será flutuante novamente , ou seja , não estará conectado a nenhum ramo. Observe que quando uma ramificação é retirada, novas confirmações sempre são colocadas automaticamente na ponta.

    Quando você quiser voltar e efetuar o check-out de uma confirmação ou marca específica para começar a trabalhar a partir daí, poderá criar uma nova ramificação originada a partir dessa confirmação e alternar para ela git checkout -b new_branch_name. Isso impedirá o Detached HEADestado, pois agora você tem uma ramificação com check-out e não uma confirmação.

Tim Skov Jacobsen
fonte
3

Uma maneira acidental simples é fazer git checkout headum erro de digitação HEAD.

Tente o seguinte:

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

que 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
Thomas Weller
fonte
Também mencionado em longair.net/blog/2012/05/07/the-most-confusing-git-terminology (procure "" HEAD "e" head "")
VonC
@VonC: obrigado por esse link. Estou preparando um treinamento para o Git e também quero mostrar por que às vezes é tão confuso. Já tenho muitos exemplos (comocheckout -b que parece um checkout, mas na verdade ramifica), mas outra lista é bem-vinda.
Thomas Weller
2

A outra maneira de entrar no estado principal desanexado do git é tentar se comprometer com uma ramificação remota. Algo como:

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

Observe que, se você fizer isso, qualquer tentativa adicional de verificar a origem / foo o levará de volta ao estado principal desanexado!

A solução é criar sua própria ramificação foo local que rastreia a origem / foo e, opcionalmente, empurre.

Provavelmente, isso não tem nada a ver com o seu problema original, mas esta página está no topo dos resultados do google para "git detached head" e esse cenário está muito sub-documentado.

dspeyer
fonte
Essa situação parece ser a resposta da Owen acima - onde cortar e colar "origin / foo" faz o git pensar nisso como "origin / origin / foo".
mvanle
1

Quando você faz o checkout para um commit git checkout <commit-hash> ou para um branch remoto, o HEAD será desanexado e tentará criar um novo commit nele.

As confirmações que não são alcançáveis ​​por nenhuma ramificação ou marca serão coletadas e removidas do lixo após 30 dias.

Outra maneira de resolver isso é criando uma nova ramificação para o commit recém-criado e finalizando a compra. git checkout -b <branch-name> <commit-hash>

Este artigo ilustra como você pode obter o estado HEAD desanexado .

Nesha Zoric
fonte