O que acontece com os commits do git criados em um estado HEAD desanexado?

137

Isso é o que aconteceu:

Eu tenho um ramo A. No ramo, o AI cometeu várias alterações. Como eu não estava satisfeito com o código, verifiquei o commit anterior no ramo A. Fiz várias alterações e o comprometi no ramo A. Agora, não consigo encontrar esse commit em nenhum lugar. Perdi esse código?

Mausimo
fonte
Quando você diz "Fiz o check-out do commit anterior no ramo A", você quer dizer "Redefini o branch A para o commit anterior"? ou seja, você realmente git resetmelhor do que git checkout?
perfil completo de CB Bailey
Não, eu usei o checkout. reflog funcionou.
Mausimo 2/12/12
Se você usou o checkout, você estará em um desanexado HEADe o ramo A permaneceria no commit anterior. Exatamente quais comandos você executou?
perfil completo de CB Bailey
1
Eu estava usando a GUI do SourceTree GIT no OSX Lion. Eu estava na ramificação A e executei uma finalização da confirmação anterior na ramificação A. Em seguida, fiz várias alterações no código e as confirmamos (ramificação A). Acredito que tinha uma CABEÇA desapegada.
Mausimo 2/12/12
OK, acho que fiquei confuso quando você disse que cometeu muitas outras alterações no ramo .
perfil completo de CB Bailey

Respostas:

185

O antigo commit ainda está no reflog.

git reflog

Isso mostrará uma lista de confirmações, e a confirmação "perdida" deve estar lá. Você pode transformá-lo em uma nova ramificação. Por exemplo, se o SHA-1 for ba5a739, você poderá criar uma nova ramificação denominada "nova ramificação" na confirmação antiga com:

git branch new-branch ba5a739

Observe que as confirmações "perdidas" serão excluídas quando o banco de dados for removido.

Dietrich Epp
fonte
3
Eu fiz a mesma coisa e tive um ataque cardíaco pensando que estava perdido. Obrigado pela informação!
Perseguição
14
Use git cherry-pick [SHA]para mover a cometer em um ramo existente no caso de você cometeu acidentalmente enquanto no estado cabeça destacada
Jan Aagaard Meier
3
Como alternativa, você pode mudar para um ramo existente e "git merge HEAD @ {n}" n correspondente ao commit "perdido" listado no reflog.
eaykin
Você sabe se o pruneexcluiria também confirmações desanexadas que estão sendo referenciadas em mensagens de confirmação? Ou isso os torna acessíveis ?
Kamafeather
@ Kamafeather: Eu não acho que isso os alcance.
Dietrich Epp
63

Seus commits ainda estão disponíveis no reflog, como já indicado. Além das outras respostas, aqui está uma maneira de assumir o controle HEAD desanexado diretamente em sua ramificação atual , sem criar e mesclar uma nova ramificação:

  1. Procure os hashes SHA-1 dos commits que você fez no estado HEAD desanexado com

    git reflog
    
  2. Em seguida, execute, com todos os hashes de confirmação ordenados do mais antigo para o mais recente:

    git cherry-pick <hash1> <hash2> <hash3> ...
    

    Por exemplo, se eu tivesse apenas um, fornecido no formato de hash "primeiros 7 caracteres":

    git cherry-pick a21d053
    

Isso criará novas confirmações para sua ramificação atual, uma confirmação por hash desanexado-HEAD-commit que você mencionou no comando. Ele também assume as mensagens de confirmação originais.

tanius
fonte
11

Você pode encontrar confirmações perdidas (dangling) com o seguinte comando:

git fsck --lost-found

Observe que, se o seu cabeçalho atual estiver comprometido, ele não será listado como perdido.

Você pode encontrar mais informações em git-fsck (1) Página do manual

Em seguida, você pode criar ramificação nesse commit perdido:

git branch new-branch ba5a739
sergtk
fonte
Eu primeiro usei o comando "git reflog" e depois "git branch new-branch ba5a739" para um submódulo, ele funcionou.
Ondermerol
7

A linguagem Git para o estado do seu diretório de trabalho é uma " CABEÇA desanexada ". Aqui está outro lugar que git reflogfaz a economia.

$ git reflog
0b40dd6 HEAD@{0}: commit: my commit on detached HEAD
...

Se eu tentar fazer checkout de um ramo diferente, o git-1.7.5.1 dará uma sugestão útil.

mestre de checkout do $ git
Aviso: você está deixando 1 commit para trás, não conectado a
qualquer um de seus ramos:

  0b40dd6 meu commit no HEAD desanexado

Se você deseja mantê-los criando uma nova ramificação, talvez seja um bom momento
para fazer isso com:

 git branch new_branch_name 0b40dd65c06bb215327863c2ca10fdb4f904215b

Comutado para a ramificação 'master'
Greg Bacon
fonte
Obrigado pela informação e link. O link me ajudou a entender o que estava acontecendo.
Mausimo 2/12/12
6

Você não o perdeu, o Git ainda mantém uma cópia (mas atualmente é inacessível por qualquer cabeçalho de ramificação). Você pode encontrar sua confirmação ausente usando o git reflogcomando O reflog monitora as posições históricas de uma cabeça de ramificação e você pode usá-lo para encontrar coisas que a cabeça de ramificação estava apontando anteriormente.

Greg Hewgill
fonte
4

Siga estas etapas para vincular sua cabeça desanexada ao repositório git

  1. git checkout "your branch with path but without remote name"

por exemplo, se o nome remoto for origem e o nome do ramo for bugfix/somebranchusadogit checkout bugfix/somebranch

  1. git reflog obtenha os SHA de confirmação listados em sua lista de confirmação do ramo desanexado.

  2. git cherry-pick "commit hash1" "commit hash2" "commit hash3"

  3. git push

TUDO PRONTO!!

user1520615
fonte
2

No Sourcetree, descobri que o git reflog não funcionava, então descobri como fazer isso usando a GUI.

Primeiro, tente encontrar o commit "perdido" procurando uma mensagem no Histórico de Comandos (exibição: Mostrar Saída de Comando). Esperamos que esteja no comando "Switching Branch" após a confirmação que você perdeu e você verá o comentário de confirmação com um ID de confirmação 1234567.

Leve esse Commit ID para a próxima etapa.

Aperte o botão "Ramificação" na barra de ferramentas superior e você deve obter uma caixa de diálogo "Nova ramificação", onde você pode especificar uma certa confirmação. Coloque esse ID de confirmação lá, especifique um novo nome de filial, pressione Criar filial e você deverá obter uma nova filial com sua confirmação perdida!

Isso trouxe de volta algum trabalho perdido para mim!

Blalond
fonte