Obtenha uma lista de todos os commits do git, incluindo os 'perdidos'

139

Digamos que eu tenha um gráfico como este:

A---B---C---D (master)
     \
      \-E---F (HEAD)

Se o fizer git log --all --oneline, receberei todos os seis dos meus commits.

Mas se o gráfico for

A---B---C---D (master, HEAD)
     \
      \-E---F

Não verei E e F. Posso fazer com que o git me conte todos os commits, incluindo aqueles em ramos que não são nomeados?

obrigado

Amadan
fonte

Respostas:

63

Não é fácil - se você perdeu o ponteiro para a ponta de um galho, é como encontrar uma agulha no palheiro. Você pode encontrar todos os commits que parecem não ter mais referência - git fsck --unreachablefarão isso por você -, mas isso incluirá commits que você jogou fora após um git commit --amend, commits antigos nos ramos que você rebatizou etc. etc. Então, vendo todos esses commits ao mesmo tempo, é provável que exista muita informação para percorrer.

Portanto, a resposta irreverente é: não perca o interesse. Mais a sério, os reflogs manterão referências a todos os commits que você usou nos últimos 60 dias, por padrão. Mais importante, eles darão algum contexto sobre o que são esses commits .

araqnid
fonte
7
+1: Não existe absolutamente nenhuma diferença entre um commit deliberadamente órfão por commit --amendou rebasee um acidentalmente órfão ao trabalhar com um HEAD desanexado, por exemplo.
Cascabel
3
de fato. provavelmente a maneira mais fácil de se recuperar dessa situação será olhar o reflog para o próprio HEAD.
Araqnid
@Jefromi: Excelente observação sobre git commit --amendetc. deixar becos sem saída, compromissos perdidos. Fiz algumas reformulações e outros enfeites e acabei com alguns commits inacessíveis a partir de quaisquer ramos, e me senti um pouco sujo deixando-os no repositório. Agora, o pensamento não é mais tão perturbador. :)
Emil Lundberg
2
@araqnid Eu me meti no mesmo ponto que o pôster original e sua sugestão de olhar para o reflog era exatamente o que deveria ser feito.
111313 Ignazio
7
Concordo com esta resposta, mas no caso em que alguém precisa ver todos os commits, incluindo os órfãos, deliberados ou acidentais, git fsck --unreachablenão fornece isso. Eu apenas tentei. A melhor abordagem é a --reflogopção para git log, como kenorb respondeu . O que é especialmente interessante nisso é que, combinado com --graph, você obtém um contexto visual fácil de analisar, muito parecido com o ilustrado na pergunta original. Por exemplo, tente:git log --graph --all --oneline --reflog
Inigo
111

Experimentar:

git log --reflog

que lista todos os commit de git fingindo que todos os objetos mencionados por reflogs ( git reflog) estão listados na linha de comando como <commit>.

kenorb
fonte
1
Era isso que eu procurava - a funcionalidade do argumento --reflog.
Anomaly
3
Btw, o gitk também suporta isso: gitk --reflog.
ald.li
50

Quando resolvo esse problema, uso o seguinte comando:

git reflog |  awk '{ print $1 }' | xargs gitk

Isso permite visualizar confirmações recentes que se tornaram sem cabeça.

Eu tenho isso embrulhado em um auxiliar de script chamado ~/bin/git-reflog-gitk.

Kieran
fonte
1
Isso me salvou muito tempo ... OBRIGADO!
Bret Royster
isso é incrível! obrigado! realmente visualiza as partes importantes da árvore.
Mladen B.
Apenas uma dica: isso funcionará apenas para o seu trabalho local como registros de reflog when the tips of branches and other references were updated in the *local repository*. Você pode querer usar git log --reflogse quiser fazer isso para alterações de ref não locais
Krishna Gupta
29

O que salvou minha vida foi o seguinte comando:

git reflog

Lá você encontra uma tela com confirmações de histórico feitas para git como esta:

insira a descrição da imagem aqui

Nesse ponto, você só precisa encontrar o HEAD@{X}necessário, criar uma ramificação temporária e passar para ela da seguinte maneira:

git checkout -b temp_branch HEAD@{X}

Dessa forma, você terá um ramo temporário com seu commit perdido, sem rebasear ou quebrar ainda mais seu repositório git.

Espero que isto ajude...

Sonhja
fonte
26

Como a resposta de @Kieran, mas para o console: git log --oneline --all --graph --decorate $(git reflog | awk '{print $1}')

Florian Fida
fonte
Você precisa incluir a última parte: $ (git reflog | awk '{print $ 1}')? O que isso faz? Depois de experimentar sua solução, parece que ela produz a mesma saída, mesmo sem a última parte.
Wmock
Se você mover o ponteiro de ramificação e deixar alguns commit sem uma referência (como o OP fez), eles não aparecerão mais git log --all. Um exemplo rápido: após a git reset --hard @^confirmação do seu HEAD @ {0}, apenas estará no reflog e, como git reflognão suporta, --graphvocê deve passar os commits git log --graphpara obter uma representação visual.
Florian Fida
5
você pode usar em --reflogvez de $(git reflog | awk '{print $1}')
Sild
Eu comparei git log --oneline --all --graph --decorate $(git reflog | awk '{print $1}')com git log --oneline --all --graph --decorate --reflog, eles são quase idênticos, exceto --reflog incluiu detalhes como entradas WIP.
Lobo Script
@FlorianFida, em vez de reflogpor que não usar log --reflog?
Pacerier
9

Como eu resolvo esse problema? Use git fscke registre-se!

Primeiro, crie um arquivo contendo confirmações e blobs perdidos (inacessíveis). (OBSERVAÇÃO: se você fez algo assim git gc, o lixo coletará todos os commits e você não os encontrará aqui!)

$git fsck --lost-found > lost_found.commits

Isso fornece um arquivo como este:

pendurado cometer dec2c5e72a81ef06963397a49c4b068540fc0dc3
pendurada blob f8c2579e6cbfe022f08345fa7553feb08d60a975
pendurada blob 0eb3e86dc112332ceadf9bc826c49bd371acc194
pendurada blob 11cbd8eba79e01f4fd7f496b1750953146a09502
pendurada cometer 18733e44097d2c7a800650cea442febc5344f9b3
pendurada blob 1e53a5cdb3ecdde27081ec6e8b31e4070106ee05

Você pode abrir esse arquivo com o editor de texto favorito para copiar os hashes de commit / blog a partir daí. (as macros * tosse * vim funcionam muito bem para essa tosse *)

Agora você pode fazer logon novamente desse commit com algo parecido git log --oneline <commit hash>. Como alternativa, gitk, tig ou qualquer outro visualizador de git deve funcionar.

No seu caso, se você encontrar o hash para confirmação F, o log mostrará algo assim,

A---B---E---F

Rápido e fácil! Agora você pode encontrar o contexto por trás de todos esses commits dangling.

PS: Sim, eu sei, postagem tardia, mas bem, alguém pode encontrá-lo aqui e achar útil. (Provavelmente eu em 6 meses quando eu pesquisar isso novamente no Google)

bsimmons
fonte
5

Tive sorte em recuperar o commit observando o reflog, localizado em .git/logs/HEAD

Eu tive que ir até o final do arquivo e encontrei o commit que acabei de perder.

GameScripting
fonte
Isso é o que acabou de fazer quando eu estraguei alguma coisa. Tentei me comprometer a dominar e Stash recusou quando eu empurrei. Eu redefini --hard, então percebi meu erro. O commit estava no reflog, então eu verifiquei, fiz um branch dele e depois o empurrei. Tudo deu certo no final.
David David
5

Vamos git logàs vezes não é bom para obter todos os detalhes commits, de modo a ver isso ...

Para Mac: Entre no seu projeto git e digite:

$ nano .git/logs/HEAD

para ver todos vocês confirmados nisso, ou:

$ gedit .git/logs/HEAD

para ver todos vocês confirmam nisso,

então você pode editar em qualquer navegador favorito.

Vinod Joshi
fonte
3

@bsimmons

git fsck --lost-found | grep commit

Em seguida, crie uma ramificação para cada um:

$ git fsck --lost-found | grep commit
Checking object directories: 100% (256/256), done.
dangling commit 2806a32af04d1bbd7803fb899071fcf247a2b9b0
dangling commit 6d0e49efd0c1a4b5bea1235c6286f0b64c4c8de1
dangling commit 91ca9b2482a96b20dc31d2af4818d69606a229d4

$ git branch  branch_2806a3 2806a3
$ git branch  branch_6d0e49 6d0e49
$ git branch  branch_91ca9b 91ca9b

Agora, muitas ferramentas mostrarão uma visualização gráfica desses commits perdidos.

yakoda
fonte
2

Se você usar a GUI do Git Extensions, ele poderá mostrar uma visualização gráfica de confirmações pendentes se você marcar "Exibir -> Mostrar referências de reflog". Isso mostrará comprometimentos pendentes na árvore, como todos os outros referenciados. Dessa forma, é muito mais fácil encontrar o que você está procurando.

Veja esta imagem para demonstração. As confirmações C2, C3, C4 e C5 na imagem estão pendentes, mas ainda visíveis.

Zdovc
fonte
2
git log --reflog

me salvou! Perdi meu tempo mesclando HEAD e não consegui encontrar meus compromissos comprometidos! Não é exibido na árvore de origem, mas git log --reflogmostra todos os meus commits locais antes

Sultanmyrza Kasymbekov
fonte