Desfazendo pop de stash acidental do git

186

Eu escondi algumas alterações locais antes de fazer uma mesclagem complicada, fiz a mesclagem e esqueci estupidamente de confirmar antes de executar git stash pop. O pop criou alguns problemas (mau método chama em uma grande base de código) que estão se mostrando difíceis de rastrear. Eu corri git stash show, pelo menos sei quais arquivos foram alterados. Se nada mais, acho que é uma lição para comprometer mais.

Minha pergunta: é possível desfazer o stash pop sem também desfazer a mesclagem?

nren
fonte
2
Você não deve ter permissão para fazer isso git stash popantes de cometer. O que você fez para conseguir isso?
Chris Jester-Young
Não tenho certeza para ser honesto (isso foi ontem). A mesclagem não foi confirmada por conta própria porque houve conflitos. De alguma forma, eu era capaz de executar stash pop depois disso.
N1 de
1
Eu fiz isso apenas usando a versão 1.7.9.msysgit.0 do git. Eu tive arquivos unstaged e o esconderijo pop tudo apenas mesclada no.
PandaWood
Eu era capaz de executar git stash popdepois de preparar as alterações (embora eu não confirmei) com a versão 2.25.0.windows.1 do git
Artem Hevorhian
Se você indexou suas alterações e as perdeu enquanto executava stash pop/applyantes de fazer um commit, você pode disparar git fsck --lost-found. Este comando irá percorrer os blobs dangling (arquivos reais para aqueles que não estão familiarizados com a terminologia git) que foram preparados, mas não confirmados em nenhum lugar (portanto, dangling), e os colocarão no diretório .git / lost-found / , onde você pode git showver se estes são os arquivos que você está procurando.
Artem Hevorhian

Respostas:

69

Tente usar Como recuperar um stash descartado no Git? para encontrar o estoque que você colocou. Eu acho que sempre existem dois commits para um stash, pois ele preserva o índice e a cópia de trabalho (geralmente o commit do índice estará vazio). Então git showeles para ver o diff e usar patch -Rpara desaplicá-los.

Ben Jackson
fonte
6
Uau, isso funcionou. Consegui encontrar o commit do stash git fsck --no-reflog | awk '/dangling commit/ {print $3}'(no link) e encontrei o problema manualmente a partir desse diff. Obrigado!
N1
1
o fsck gera uma lista enorme. É entediante mostrar todos os SHA1 por aí. Como você faz isso ?
precisa
5
@ meson10: Infelizmente os esconderijos são mantidos em um reflog, o que seria a maneira óbvia (se eles fossem um ramo real) de olhar para a história dos esconderijos estourados. Além disso, deixe-me sugerir que um pedido de ajuda + voto negativo não é a melhor estratégia.
Ben Jackson
2
Levei um pouco de confusão para acertar. Aqui está o resultado do meu trabalho git diff -p ${STACH_SHA1}~1 ${STASH_SHA1} | patch -R -p1:; Eu tentei com git showo sugerido, mas sua saída não era boa para o patch; também tive que fornecer a -p1opção de corrigir para remover o elemento a/..e b/..que git diffcoloca na frente dos arquivos, caso contrário não resolveria os caminhos da raiz do repositório. SUGESTÃO: seja cauteloso e cometa a bagunça em um galho separado antes de jogar com o patch.
22417 Basilicode
@ BenJackson Na sua resposta "sempre" significa ambos stash pope stash pushacionará uma confirmação que salvaria as alterações no índice e no diretório de trabalho, certo?
Artem Hevorhian 07/04
36

De git stash --help

Recovering stashes that were cleared/dropped erroneously
   If you mistakenly drop or clear stashes, they cannot be recovered through the normal safety mechanisms. However, you can try the
   following incantation to get a list of stashes that are still in your repository, but not reachable any more:

       git fsck --unreachable |
       grep commit | cut -d\  -f3 |
       xargs git log --merges --no-walk --grep=WIP

Isso me ajudou melhor do que a resposta aceita no mesmo cenário.

kachar
fonte
13
Observe que muitas soluções que envolvem a pesquisa de "WIP" contam com as mensagens stash padrão. Se você der aos seus stashes mensagens explícitas, eles podem não conter WIP.
Ben Jackson
obrigado. Eu adicionei a opção --oneline ao comando log para melhorar a legibilidade.
basslo
Isso apenas ajuda a encontrar o SHA do commit do stash. Mas se integrado ao comentário @basilikode da resposta aceita (git diff SHA ~ 1 SHA | patch -R), funciona bem. Eu recomendo usar path --dry-run primeiro para verificar.
Jarek C
3

Se sua mesclagem não fosse muito complicada, outra opção seria:

  1. Mova todas as alterações, incluindo as alterações de mesclagem, de volta ao stash usando "git stash"
  2. Execute a mesclagem novamente e confirme suas alterações (sem as alterações do stash descartado)
  3. Execute um "git stash pop" que deve ignorar todas as alterações da mesclagem anterior, pois os arquivos são idênticos agora.

Depois disso, você ficará com apenas as alterações do estoque que você deixou cair muito cedo.

markus
fonte