Corrigir uma cabeça separada do Git?

1455

Eu estava trabalhando no meu repositório e percebi que um arquivo tinha alterações locais. Eu não os queria mais, então apaguei o arquivo, pensando em fazer o checkout de uma nova cópia. Eu queria fazer o equivalente Git de

svn up .

Usar git pullnão parecia funcionar. Algumas pesquisas aleatórias me levaram a um site onde alguém recomendava fazer

git checkout HEAD^ src/

( srcé o diretório que contém o arquivo excluído).

Agora descubro que tenho uma cabeça desapegada. Eu não tenho ideia do que é isso. Como posso desfazer?

Daniel
fonte
69
git checkout mastervocê voltará ao ramo principal. Se você quisesse limpar as alterações das cópias de trabalho, provavelmente desejaria fazê-lo git reset --hard.
perfil completo de Abe Voelker
se você não tiver cometido você poderia ter feitogit checkout -- src/
thesummersign
Tente o seguinte: link . Resumindocreate temp branch - checkout temp branch - checkout master - delete temp branch
fidev 2/06
@AbeVoelker O que você quis dizer com nos comentários working copy changes? Você está se referindo às alterações que você fez nos arquivos após verificar outro commit (ou seja, as alterações que você fez enquanto estava no estado principal desanexado)?
Minh Tran

Respostas:

2148

Cabeça desanexada significa que você não está mais em um ramo, fez check-out de um único commit no histórico (nesse caso, o commit anterior ao HEAD, ou seja, HEAD ^).

Se você deseja excluir suas alterações associadas ao HEAD desanexado

Você só precisa fazer check-out da filial em que estava, por exemplo

git checkout master

Na próxima vez que você alterar um arquivo e quiser restaurá-lo para o estado em que está no índice, não exclua o arquivo primeiro, apenas faça

git checkout -- path/to/foo

Isso restaurará o arquivo foo para o estado em que está no índice.

Se você deseja manter suas alterações associadas ao HEAD desanexado

  1. Executar git branch tmp- isso salvará suas alterações em um novo ramo chamado tmp.
  2. Corre git checkout master
  3. Se você deseja incorporar as alterações feitas master, execute a git merge tmppartir da masterramificação. Você deve estar no masterramo depois de executar git checkout master.
ralphtheninja
fonte
6
"Isso restaurará o arquivo foo ao estado em que estava antes de fazer alterações nele." -> ele irá restaurá-lo para o estado em que está no índice - por favor edite
Mr_and_Mrs_D
88
Por que esse erro ocorre em primeiro lugar? Essa é uma das coisas pelas quais eu odeio o git - comportamento totalmente aleatório às vezes. Nunca tive problemas com o Mercurial.
Giraffe Violet
97
@VioletGiraffe Não é um erro nem algo aleatório - é simplesmente o estado em que seu repositório entra quando você faz o checkout de uma confirmação anterior. O "Cabeça desanexada" serve como um aviso de que você também pode criar ou apontar para uma ramificação, se pretender fazer algum trabalho a partir desse ponto. Mas se você simplesmente deseja visualizar essa tag ou confirmar, não há nada de errado em estar em um estado principal desanexado.
Neil Neyman
22
Não faça isso se você se comprometeu com a cabeça desapegada, veja outras respostas. Em caso afirmativo, você pode conferir as referências anteriores do head git emPrevious HEAD position was 7426948...
KCD
9
@VioletGiraffe: você tem um modelo mental do que está acontecendo com base no Mercurial, mas está usando o Git. Se você não estiver disposto a ajustar seu modelo mental para se ajustar ao modelo de Git, as coisas continuarão a parecer aleatórias. É como se você estivesse andando lá fora com os óculos de realidade virtual, e você pensa que está pilotando um avião, mas está realmente atravessando a rua. Você vai ser atropelado por carros.
Iconoclasta
477

Se você alterou os arquivos que não deseja perder, pode pressioná-los. Eu os comprometi no modo desanexado e depois disso você pode passar para uma ramificação temporária para integrar mais tarde no mestre.

git commit -m "....."
git branch my-temporary-work
git checkout master
git merge my-temporary-work

Extraído de:

O que fazer com o commit feito em uma cabeça desanexada

Toni Gamez
fonte
27
Acho que essa é a solução preferida - especialmente se você deseja manter as alterações feitas ao fazer o check-out da versão individual.
adswebwork
10
@adswebwork: eu concordo. Todas as outras respostas sugerem reverter para um estado anterior e perder as alterações feitas localmente no estado principal desanexado.
Sk8erPeter
6
por que não git stash? Como essa é a primeira coisa que me vem à cabeça. criar um novo ramo será um exagero.
Thesummersign
2
você também pode git rebase my-temporary-workexcluir a ramificação git branch -d my-temporary-workpara que ela pareça que você se comprometeu com a ramificação direita em primeiro lugar.
Zoltán
@geekay git stashparece a ferramenta perfeita para este caso. Você poderia escrever uma resposta com as etapas sugeridas para conseguir isso?
Zoltán
157

Uma solução sem criar uma ramificação temporária.

Como sair ("corrigir") do estado HEAD desanexado quando você já alterou algo neste modo e, opcionalmente, deseja salvar suas alterações:

  1. Confirme as alterações que deseja manter. Se você deseja assumir qualquer uma das alterações feitas no estado HEAD desanexado, confirme-as. Gostar:

    git commit -a -m "your commit message"
    
  2. Descarte as alterações que você não deseja manter. A redefinição física descartará quaisquer alterações não confirmadas que você fez no estado HEAD desanexado:

    git reset --hard
    

    (Sem isso, a etapa 3 falharia, reclamando sobre arquivos não confirmados modificados no HEAD desanexado.)

  3. Confira sua filial. Saia do estado HEAD desanexado, verificando a ramificação na qual você trabalhou antes, por exemplo:

    git checkout master
    
  4. Assuma o controle de seus commits. Agora você pode assumir os commits que você fez no estado HEAD desanexado escolhendo cereja, conforme mostrado na minha resposta a outra pergunta .

    git reflog
    git cherry-pick <hash1> <hash2> <hash3> …
    
tanius
fonte
O git reset --hardfoi exatamente foi que eu precisava, porque eu quero que o montante a ser a fonte e as mudanças locais devem ser removidos.
Markus Zeller
Ótima resposta, isso funcionou para mim
MGLondon
130

Cabeça destacada significa:

  1. Você não está mais em um galho,
  2. Você fez check-out de um único commit no histórico

Se não houver alterações: você pode alternar para o mestre aplicando o seguinte comando

  git checkout master

Se você tiver alterações que deseja manter:

No caso de um HEAD desanexado, confirma o trabalho normalmente, exceto que nenhuma ramificação nomeada é atualizada. Para atualizar a ramificação principal com suas alterações confirmadas, faça uma ramificação temporária onde você está (dessa forma, a ramificação temporária terá todas as alterações confirmadas que você fez no HEAD desanexado), depois mude para a ramificação principal e mescle a ramificação temporária com O mestre.

git branch  temp
git checkout master
git merge temp
Razan Paul
fonte
2
perfeito, depois de remover a temperatura da ramificação
Davi Menezes
64

Aqui está o que eu fiz depois que percebi que estava com uma cabeça desapegada e que já havia feito algumas alterações.

Eu cometi as mudanças.

$ git commit -m "..."
[detached HEAD 1fe56ad] ...

Lembrei-me do hash (1fe56ad) do commit. Então verifiquei o ramo em que deveria estar.

$ git checkout master
Switched to branch 'master'

Por fim, apliquei as alterações do commit no ramo.

$ git cherry-pick 1fe56ad
[master 0b05f1e] ...

Eu acho que isso é um pouco mais fácil do que criar um ramo temporário.

Philippe Gerber
fonte
2
Essa deve ser a resposta. Ele recupera seus arquivos com nuked.
BlindWanderer 12/10
2
Sim, essa é realmente a coisa mais simples a se fazer - simples o suficiente para lembrar sem pesquisar na web na próxima vez que isso acontecer. Confirmar, anotar hash, retornar à ramificação com a qual você pretendia se comprometer e git cherry-pick <hash>.
Mason
Obrigado pela solução. Isso ajudou. Devo também acrescentar que eu tive que fazer um "mestre de origem do git push" para que meu mestre e origem / mestre estivessem apontando para o mesmo commit.
Turnip424
1
Esta é essencialmente a resposta do tanius (postada mais de um ano antes).
Peter Mortensen
Graças a essa paleta animada, reverter as últimas alterações na cabeça de desanexação
Omega Cube
55

Se você fez algumas alterações e percebeu que está com uma cabeça desanexada, existe uma solução simples para isso: stash -> checkout master -> stash pop:

git stash
git checkout master   # Fix the detached head state
git stash pop         # Or for extra safety use 'stash apply' then later 
                      #   after fixing everything do 'stash drop'

Você terá suas alterações não confirmadas e o HEAD "anexado" normal, como se nada tivesse acontecido.

mojuba
fonte
2
Marcou este menino mau - salva fazendo um ramo temporário. Trabalhou um prazer.
Tim Tyler
1
Costumo terminar em um estado HEAD desanexado depois de verificar um submódulo git e depois fazer alterações nele. Acho que essa é a melhor e mais fácil solução para consertar as coisas, para que eu possa preservar minhas alterações.
user5359531
1
Isso não funciona se você já efetuou alterações em um estado desanexado?
Danijel
40

Quando você faz check-out de um commit específico git, você acaba em um estado principal desanexado ... ou seja, sua cópia de trabalho não reflete mais o estado de uma referência nomeada (como "mestre"). Isso é útil para examinar o estado passado do repositório, mas não o que você deseja se estiver realmente tentando reverter alterações.

Se você fez alterações em um arquivo específico e deseja simplesmente descartá-las, pode usar o checkoutcomando desta forma:

git checkout myfile

Isso descartará quaisquer alterações não confirmadas e reverterá o arquivo para qualquer estado que ele tenha no cabeçalho de sua ramificação atual. Se você deseja descartar as alterações que você já confirmou, convém usar o resetcomando Por exemplo, isso redefinirá o repositório para o estado da confirmação anterior, descartando quaisquer alterações subsequentes:

git reset --hard HEAD^

No entanto, se você estiver compartilhando o repositório com outras pessoas, a git resetpoderá ser perturbadora (porque apaga uma parte do histórico do repositório). Se você já compartilhou alterações com outras pessoas, geralmente deseja examinar git revert, o que gera um "anticommit", isto é, cria um novo commit que "desfaz" as alterações em questão.

O livro Git tem mais detalhes.

larsks
fonte
1
Como eu disse na resposta de @ ralphtheninja, git checkout path/to/foopoderia entrar em conflito com git checkout some-branch, portanto, seria melhor usá-lo git checkout -- path/to/foopara evitar esses conflitos.
Diego Lago
30

HEAD está em um ponteiro e, como resultado, aponta - direta ou indiretamente - para um commit específico:

  HEAD anexado significa que está anexado a algum ramo (isto é, aponta para um ramo).
Separada meios CABEÇA que se não associadas a qualquer ramo, ou seja, ele aponta diretamente para alguns cometem.

insira a descrição da imagem aqui

Em outras palavras:

  • Se apontar para um commit diretamente , o HEAD será desanexado .
  • Se apontar para um commit indiretamente (ou seja, apontar para um branch, que por sua vez aponta para um commit), o HEAD será anexado .

Para entender melhor as situações com o HEAD anexado / desanexado, vamos mostrar as etapas que levam ao quadrupleto das fotos acima.

Começamos com o mesmo estado do repositório (as imagens em todos os quadrantes são iguais):

insira a descrição da imagem aqui


Agora queremos realizar git checkout- com diferentes alvos em imagens individuais (comandos em cima deles estão desactivados para enfatizar que estamos apenas indo para aplicar esses comandos):

insira a descrição da imagem aqui


Esta é a situação após a execução desses comandos:

insira a descrição da imagem aqui

Como você pode ver, o HEAD aponta para o alvo do git checkoutcomando - para um ramo (primeiras 3 imagens do quádruplo) ou (diretamente) para um commit (a última imagem do quádruplo).

O conteúdo do diretório de trabalho também é alterado para estar de acordo com o commit apropriado (instantâneo), ou seja, com o commit apontado (direta ou indiretamente) pelo HEAD.


Então, agora estamos na mesma situação que no início desta resposta:

insira a descrição da imagem aqui

MarianD
fonte
6
Não li, mas votei nas fotos bonitas que você fez;).
Carlo Wood
@Carlo, obrigado!
MarianD 5/01
22

Como "estado principal desanexado" o git checkout -coloca em uma ramificação temporária, basta usar o que coloca você na última ramificação em que você esteve.

Mike
fonte
1
tenha cuidado, você perderá quaisquer confirmações feitas quando estava no estado principal desanexado.
Ajak6
@ Ajak6 Você realmente não perde esses commits. Eles ainda estão disponíveis via git refloge podem ser transferidos para uma nova ramificação ou via git cherry-pickpara uma ramificação existente. Veja esta pergunta .
tanius
7

Para esclarecer melhor a resposta de @Philippe Gerber, aqui está:

git cherry-pick

Antes cherry-pick, a git checkout masteré necessário neste caso. Além disso, é necessário apenas com um commitin detached head.

Timo
fonte
6

Termo aditivo

Se o ramo para o qual você deseja retornar foi o último check-out que você fez, basta usar checkout @{-1}. Isso levará você de volta ao seu checkout anterior.

Além disso, você pode alternar esse comando com, por exemplo, git global --config alias.prevpara que você só precise digitar git prevpara voltar ao checkout anterior.

David Brower
fonte
4

Estar na "cabeça desanexada" significa que HEAD se refere a um commit específico sem nome (em oposição a uma ramificação nomeada) (consulte: https://git-scm.com/docs/git-checkout section Cabeça desanexada )

Para corrigir o problema, você só precisa selecionar a ramificação que foi selecionada anteriormente por

git checkout @{-1}

Pat. ANDRIA
fonte
2

Quando você estiver em uma situação de desanexação e criar novos arquivos, primeiro verifique se esses novos arquivos foram adicionados ao índice, por exemplo:

git add .

Mas se você alterou ou excluiu apenas os arquivos existentes, é possível adicionar (-a) e confirmar com uma mensagem (-m) ao mesmo tempo via:

git commit -a -m "my adjustment message"

Em seguida, você pode simplesmente criar uma nova ramificação com seu estado atual com:

git checkout -b new_branch_name

Você terá uma nova ramificação e todos os seus ajustes estarão lá nessa nova ramificação. Você pode continuar pressionando o controle remoto e / ou efetuando checkout / pull / mesclar como desejar.

DZet
fonte
1

Git me disse como fazê-lo.

se você digitou:

git checkout <some-commit_number>

Salve o status

git add .
git commit -m "some message"

Então:

 git push origin HEAD:<name-of-remote-branch>
Sterling Diaz
fonte
1

Eu queria manter minhas alterações, apenas consertei isso ...

git add .
git commit -m "Title" -m "Description"
(so i have a commit now example: 123abc)
git checkout YOURCURRENTBRANCH
git merge 123abc
git push TOYOURCURRENTBRANCH

isso funciona para mim

CRLZXO
fonte
1

Normalmente HEADaponta para um ramo. Quando não está apontando para uma ramificação, quando aponta para um hash de confirmação 69e51, significa que você tem um HEAD desanexado. Você precisa apontar dois ramos para corrigir o problema. Você pode fazer duas coisas para corrigi-lo.

  1. git checkout other_branch // Não é possível quando você precisa do código nesse commit hash
  2. crie uma nova ramificação e aponte o hash de confirmação para a ramificação recém-criada.

O HEAD deve apontar para um ramo, e não um hash de confirmação é a regra de ouro.

Krishnadas PC
fonte
é por isso que tive esse mesmo erro. Fiz check-out para uma revisão e, em seguida, voltei novamente para a revisão atual / mais recente, em vez de fazer check-out no ramo, que teria anexado a cabeça corretamente. Obrigado pela ajuda.
Rahul Thakur
1

Cabeça desanexada significa que você não efetuou o check-out de seu ramo corretamente ou apenas efetuou o check-out de um único commit.

Se você encontrar esse problema, primeiro esconda as alterações locais para não perdê-las.

Depois disso ... efetue o checkout do ramo desejado usando o comando:

Digamos que você queira o ramo MyOriginalBranch:

git checkout -b someName origem / MyOriginalBranch

Dhirendra Gautam
fonte
1

você provavelmente fez git reset --hard origin/your-branch.

Tente apenas git checkout your-branch

Johnny Cage
fonte
0
git pull origin master

trabalhou para mim. Era apenas dar um nome remoto e de filial explicitamente.

Amjedonline
fonte
0

No meu caso, eu corro git statuse vi que havia alguns arquivos não rastreados no meu diretório de trabalho.

Eu só tinha que limpá-los (já que não precisava deles) para executar o rebase que queria realizar.

falsarella
fonte
0

Isso funciona para mim, ele atribuirá uma nova ramificação para a cabeça desanexada:

git checkout new_branch_name detached_head_garbage_name

Alok Gupta
fonte
0

O HEAD desanexado significa que você não está atualmente em nenhum ramo. Se você deseja manter suas alterações atuais e simplesmente criar uma nova ramificação, é isso que você faz:

git commit -m "your commit message"
git checkout -b new_branch

Posteriormente, você deseja mesclar esse novo ramo com outros ramos. Sempre útil é o comando git "a dog" :

git log --all --decorate --oneline --graph
gebbissimo
fonte