Eu freqüentemente uso git stash
e git stash pop
para salvar e restaurar alterações na minha árvore de trabalho. Ontem, tive algumas alterações na minha árvore de trabalho que havia escondido e aparado e, em seguida, fiz mais alterações na minha árvore de trabalho. Gostaria de voltar e revisar as alterações ocultas de ontem, mas git stash pop
parece remover todas as referências ao commit associado.
Eu sei que, se eu usar git stash
, o .git / refs / stash contém a referência do commit usado para criar o stash. E .git / logs / refs / stash contém todo o stash. Mas essas referências se foram depois git stash pop
. Eu sei que o commit ainda está no meu repositório em algum lugar, mas não sei o que era.
Existe uma maneira fácil de recuperar a referência de confirmação de stash de ontem?
Observe que isso não é crítico para mim hoje porque tenho backups diários e posso voltar à árvore de trabalho de ontem para obter minhas alterações. Estou perguntando, porque deve haver uma maneira mais fácil!
git stash pop
, poderá fazê-logit stash apply
. Faz o mesmo, exceto que não remove a referência ao stash aplicado.git stash
,git pull -r upstream
,git push -f origin
,git stash pop
, e pop disse "fatal: log para refs / estoque está vazio". 😲 Tentei várias respostas, nada funcionou. Quando procurei em .git / refs / stash , o SHA estava lá. Talvez um problema ao marcar uma unidade de rede do Windows para sincronização offline? --️Respostas:
Depois de saber o hash do commit do stash que você eliminou, você pode aplicá-lo como um stash:
Ou, você pode criar uma ramificação separada para isso com
Depois disso, você pode fazer o que quiser com todas as ferramentas normais. Quando terminar, apenas sopre o galho.
Encontrando o hash
Se você apenas o abriu e o terminal ainda está aberto, você ainda terá o valor do hash impresso
git stash pop
na tela (obrigado, Dolda).Caso contrário, você pode encontrá-lo usando isso para Linux, Unix ou Git Bash para Windows:
... ou usando o Powershell para Windows:
Isso mostrará a você todas as confirmações nas dicas do gráfico de confirmação que não são mais referenciadas em nenhuma ramificação ou tag - toda confirmação perdida, incluindo toda confirmação de stash que você já criou, estará em algum lugar desse gráfico.
A maneira mais fácil de encontrar o commit stash desejado é provavelmente passar essa lista para
gitk
:... ou veja a resposta de emragins se estiver usando o Powershell para Windows.
Isso iniciará um navegador de repositório, mostrando todos os commit no repositório de todos os tempos , independentemente de serem alcançáveis ou não.
Você pode substituí
gitk
-lo por algo comogit log --graph --oneline --decorate
se você preferir um bom gráfico no console do que um aplicativo GUI separado.Para detectar confirmações de stash, procure por mensagens de confirmação deste formulário:
WIP em somebranch : commithash Alguma mensagem antiga de commit
Nota : A mensagem de confirmação estará neste formato apenas (começando com "WIP ativado") se você não forneceu uma mensagem quando o fez
git stash
.fonte
%{ $_.Split(' ')[2]; }
deve fazer o equivalente do{print $3}
em queawk
comando em PowerShell, mas eu não tenho um sistema do Windows para testar isso, e você ainda precisa de um equivalente para a/dangling commit/
parte. De qualquer forma, basta executargit fsck --no-reflog
e olhar para a saída. Você deseja os hashes das linhas "dangling commit <commitID>".git stash save "<message>"
).git fsck --no-reflog | awk '/dangling commit/ {print $3}' | xargs -L 1 git --no-pager show -s --format="%ci %H" | sort
a última entrada é provavelmente a que você desejastash apply
.git stash apply {ref}
restaurou um esconderijo caído!git
é tão bom que deveria ser ilegal!Se você não fechou o terminal, basta olhar para a saída
git stash pop
e você terá o ID do objeto do estoque descartado. Normalmente é assim:(Observe que
git stash drop
também produz a mesma linha.)Para recuperar esse estoque, basta executar
git branch tmp 2cae03e
e você o obterá como um ramo. Para converter isso em um esconderijo, execute:Tê-lo como um ramo também permite manipulá-lo livremente; por exemplo, para selecioná-lo ou mesclá-lo.
fonte
git stash apply commitid
issogit stash
para obter um novo esconderijo.git stash pop
, ele também não eliminará o estoque, então isso normalmente não é um problema.git stash pop
. Se você deseja aplicar o esconderijo sem soltá-lo, use-ogit stash apply
. Além disso, se você deseja aplicar uma alteração em várias ramificações, também pode escolher a confirmação.Só queria mencionar essa adição à solução aceita. Não foi imediatamente óbvio para mim na primeira vez que tentei esse método (talvez devesse ter sido), mas para aplicar o stash a partir do valor de hash, basta usar "git stash apply":
Quando eu era novo no git, isso não estava claro para mim, e eu estava tentando diferentes combinações de "git show", "git apply", "patch" etc.
fonte
Para obter a lista de stashes que ainda estão no seu repositório, mas não são mais acessíveis:
Se você deu um título ao seu esconderijo, substitua "WIP" no
-grep=WIP
final do comando por uma parte da sua mensagem, por exemplo-grep=Tesselation
.O comando está aguardando "WIP" porque a mensagem de confirmação padrão para uma ocultação está no formato
WIP on mybranch: [previous-commit-hash] Message of the previous commit.
fonte
!
).Acabei de construir um comando que me ajudou a encontrar meu commit de stash perdido:
Isso lista todos os objetos na árvore .git / objects, localiza aqueles que são do tipo commit e mostra um resumo de cada um. A partir desse ponto, era apenas uma questão de examinar os commits para encontrar um "WIP on work: 6a9bb2" apropriado ("work" é meu ramo, 619bb2 é um commit recente).
Observo que, se eu usar "git stash apply" em vez de "git stash pop", não teria esse problema e, se usar "git stash save message ", a confirmação poderá ter sido mais fácil de encontrar.
Atualização: Com a idéia de Nathan, isso se torna mais curto:
fonte
git fsck --unreachable | grep commit
deve mostrar o sha1, embora a lista retornada possa ser bastante grande.git show <sha1>
mostrará se é o commit que você deseja.git cherry-pick -m 1 <sha1>
mesclará o commit na ramificação atual.fonte
Equivalente ao Windows PowerShell usando o gitk:
gitk --all $(git fsck --no-reflog | Select-String "(dangling commit )(.*)" | %{ $_.Line.Split(' ')[2] })
Provavelmente, existe uma maneira mais eficiente de fazer isso em um pipe, mas isso faz o trabalho.
fonte
Se você deseja restabelecer um stash perdido, primeiro precisa encontrar o hash do seu stash perdido.
Como Aristóteles Pagaltzis sugeriu uma
git fsck
deve ajudá-lo.Pessoalmente, uso meu
log-all
alias, que mostra todas as confirmações (confirmações recuperáveis) para ter uma visão melhor da situação:Você pode fazer uma pesquisa ainda mais rápida se estiver procurando apenas mensagens "WIP on".
Depois de conhecer o sha1, basta alterar o reflog do stash para adicionar o stash antigo:
Você provavelmente prefere ter uma mensagem associada para que
-m
E você ainda vai querer usar isso como um alias:
fonte
-d\\
deve ser-d\
(ou ainda mais claro-d' '
)git update-ref -m "$(git log -1 --pretty=format:'%s' ed6721d)" refs/stash ed6721
Eu gostei da abordagem de Aristóteles, mas não gostei de usar o GITK ... como estou acostumado a usar o GIT na linha de comando.
Em vez disso, peguei as confirmações pendentes e produzi o código em um arquivo DIFF para revisão no meu editor de código.
Agora você pode carregar o arquivo diff / txt resultante (na sua pasta pessoal) no editor de txt e ver o código real e o SHA resultante.
Então é só usar
fonte
Você pode listar todos os commits inacessíveis escrevendo este comando no terminal -
Verificar hash de confirmação inacessível -
Por fim, aplique se você encontrar o item escondido
fonte
Por que as pessoas fazem essa pergunta? Porque eles ainda não conhecem ou entendem o reflog.
A maioria das respostas a essa pergunta fornece comandos longos com opções que quase ninguém se lembrará. Assim, as pessoas entram nessa questão e copiam e colam o que acham que precisam e esquecem-na quase imediatamente depois.
Eu aconselharia a todos com esta pergunta que apenas checassem o reflog (git reflog), não muito mais que isso. Depois de ver a lista de todos os commits, existem centenas de maneiras de descobrir qual commit você está procurando e selecioná-lo ou criar um branch a partir dele. No processo, você aprenderá sobre o reflog e as opções úteis para vários comandos básicos do git.
fonte
No OSX com o git v2.6.4, eu apenas corro o git stash drop acidentalmente, e o encontrei seguindo as etapas abaixo
Se você souber o nome do esconderijo, use:
$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show | grep -B 6 -A 2 <name of the stash>
caso contrário, você encontrará o ID do resultado manualmente com:
$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show
Então, quando você encontrar o commit-id, basta clicar no git stash apply {commit-id}
Espero que isso ajude alguém rapidamente
fonte
Quero adicionar à solução aceita outra boa maneira de passar por todas as alterações, quando você não tem o gitk disponível ou não há X para saída.
Então você obtém todas as diferenças para esses hashes exibidos um após o outro. Pressione 'q' para chegar ao próximo diff.
fonte
Não consegui obter nenhuma das respostas para funcionar no Windows em uma janela de comando simples (Windows 7 no meu caso).
awk
,grep
eSelect-string
não foram reconhecidos como comandos. Então, tentei uma abordagem diferente:git fsck --unreachable | findstr "commit"
start cmd /k git show
será algo como isto:
start cmd /k git show 8506d235f935b92df65d58e7d75e9441220537a4 start cmd /k git show 44078733e1b36962571019126243782421fcd8ae start cmd /k git show ec09069ec893db4ec1901f94eefc8dc606b1dbf1 start cmd /k git show d00aab9198e8b81d052d90720165e48b287c302e
git stash apply (your hash)
pode não ser a melhor solução, mas funcionou para mim
fonte
A resposta aceita por Aristóteles mostrará todos os commits alcançáveis, incluindo commits não semelhantes a stash. Para filtrar o ruído:
Isso incluirá apenas confirmações com exatamente 3 confirmações principais (que terão um stash) e cuja mensagem inclui "WIP ativado".
Lembre-se de que, se você salvou seu estoque com uma mensagem (por exemplo
git stash save "My newly created stash"
), isso substituirá a mensagem "WIP on ..." padrão.Você pode exibir mais informações sobre cada confirmação, por exemplo, exibir a mensagem de confirmação ou passá-la para
git stash show
:fonte
O meu favorito é este one-liner:
Esta é basicamente a mesma idéia que essa resposta, mas muito mais curta. Obviamente, você ainda pode adicionar
--graph
para obter uma exibição em forma de árvore.Quando você encontrar o commit na lista, aplique com
Para mim, o uso
--no-reflogs
revelou a entrada de stash perdido, mas--unreachable
(como encontrado em muitas outras respostas) não.Execute-o no git bash quando estiver no Windows.
Créditos: Os detalhes dos comandos acima são obtidos em https://gist.github.com/joseluisq/7f0f1402f05c45bac10814a9e38f81bf
fonte
Recuperou-o usando as seguintes etapas:
Identifique o código de hash stash excluído:
gitk --all $ (git fsck --no-reflog | awk '/ dangling commit / {print $ 3}')
Cereja Escolha o esconderijo:
git cherry-pick -m 1 $ stash_hash_code
Resolver conflitos, se houver, usando:
git mergetool
Além disso, você pode estar tendo problemas com a mensagem de confirmação se estiver usando o gerrit. Guarde suas alterações antes de seguir as próximas alternativas:
fonte
O que eu vim aqui procurando é como recuperar o esconderijo, independentemente do que eu verifiquei. Em particular, eu escondi algo, depois fiz o check-out de uma versão mais antiga e a abri, mas o esconderijo não era uma opção naquele momento anterior, então o esconderijo desapareceu; Eu não poderia simplesmente fazer
git stash
isso de volta na pilha. Isso funcionou para mim:Em retrospecto, eu deveria estar usando
git stash apply
nãogit stash pop
. Eu estava fazendo umbisect
e tinha um pequeno patch que queria aplicar a cadabisect
passo. Agora eu estou fazendo isso:fonte
stash apply
.