Como recuperar alterações não confirmadas ocultas

690

Tive algumas alterações não confirmadas no meu ramo de desenvolvimento e as escondi usando-as git stash, mas houve algumas que foram muito importantes entre as escondidas. Existe alguma maneira de recuperar essas alterações?

Além disso, fiz algumas alterações em cima dos arquivos de código ocultos desde então.

Existe alguma chance de recuperar as alterações ocultas em uma nova ramificação, se possível?

Aswathy P Krishnan
fonte
7
você já tentou usar 'stash pop'?
Robert
Não. Na verdade, sou novo no git. Como não estou totalmente ciente de todos os comandos, não tentei mais nada! Eu não quero perder essas mudanças.
Aswathy P Krishnan
33
Se você não deseja perder as alterações ocultas, tente usar 'git stash apply'. Isso aplicará as alterações ocultas à sua ramificação atual, mantendo ainda a ocultação. Se estiver tudo bem, depois de aplicar o stash, você pode soltá-lo usando 'git stash drop' #
robert
2
@robert Obrigado pela resposta simples, em comparação com a resposta aceita terrivelmente complicada (para um novato).
precisa saber é o seguinte

Respostas:

1184

A resposta fácil para a pergunta fácil é git stash apply

Basta verificar a ramificação na qual deseja alterar e, em seguida git stash apply. Então use git diffpara ver o resultado.

Depois está tudo feito com o seu mudanças a applyaparência boa e você está certo, você não precisa a muamba qualquer mais- então usar git stash droppara se livrar dele.

Eu sempre sugiro usar git stash applyao invés de git stash pop. A diferença é que applydeixa o esconderijo para facilitar a tentativa de apply, ou para olhar, etc. Se popfor capaz de extrair o esconderijo, ele também dropo fará imediatamente , e se você perceber de repente que queria extraí-lo em algum lugar mais (em um ramo diferente), ou com --index, ou algo assim, não é tão fácil. Se você apply, você escolhe quando drop.

É tudo bem menor, de um jeito ou de outro, e para um novato, deve ser o mesmo. (E você pode pular todo o resto!)


E se você estiver fazendo coisas mais avançadas ou mais complicadas?

Existem pelo menos três ou quatro diferentes "maneiras de usar o git stash", por assim dizer. O texto acima é para "caminho 1", o "caminho fácil":

  1. Você começou com uma ramificação limpa, estava trabalhando em algumas alterações e depois percebeu que estava fazendo-as na ramificação errada. Você só quer fazer as alterações que você tem agora e "movê-las" para outro ramo.

    Este é o caso fácil, descrito acima. Corra git stash save(ou simplesmente git stash, a mesma coisa). Confira o outro ramo e use git stash apply. Isso faz com que o git se mescle em suas alterações anteriores, usando o mecanismo de mesclagem bastante poderoso do git. Inspecione os resultados com cuidado (com git diff) para ver se você gosta deles e, se quiser, use git stash droppara soltar o estoque. Você Terminou!

  2. Você iniciou algumas alterações e as ocultou. Então você mudou para outro ramo e iniciou mais alterações, esquecendo que tinha as escondidas.

    Agora você deseja manter ou até mover essas mudanças e aplicar seu estoque também.

    Você pode de fato git stash savenovamente, como git stashfaz uma "pilha" de alterações. Se você fizer isso, terá dois esconderijos, um chamado stash- mas você também pode escrever stash@{0}- e outro escrito stash@{1}. Use git stash list(a qualquer momento) para ver todos eles. O mais novo é sempre o número mais baixo. Quando você git stash dropsolta o mais novo e o que foi stash@{1}movido para o topo da pilha. Se você tivesse ainda mais, o que era stash@{2}se tornaria stash@{1}, e assim por diante.

    Você pode applye, em seguida, dropum estoque específico também: git stash apply stash@{2}e assim por diante. Soltar um estoque específico, renumera apenas os de maior número. Novamente, aquele sem número também é stash@{0}.

    Se você empilhar muitos stashes, pode ficar bastante confuso (era o stash que eu queria stash@{7}ou era stash@{4}? Espere, eu apenas empurrei outro, agora são 8 e 5?). Pessoalmente, prefiro transferir essas alterações para um novo ramo, porque os ramos têm nomes e cleanup-attempt-in-Decembersignificam muito mais para mim do que stash@{12}. (O git stashcomando recebe uma mensagem opcional de salvamento e eles podem ajudar, mas de alguma forma, todos os meus stashes acabam nomeados WIP on branch.)

  3. (Extra avançado) Você usou git stash save -p, ou bits específicos do seu código com cuidado git adde / ou git rmantes de executar git stash save. Você tinha uma versão na área de índice / armazenamento temporário, e outra versão (diferente) na árvore de trabalho. Você quer preservar tudo isso. Então agora você usa git stash apply --index, e isso às vezes falha com:

    Conflicts in index.  Try without --index.
    
  4. Você está usando git stash save --keep-indexpara testar "o que será comprometido". Este está além do escopo desta resposta; veja esta outra resposta StackOverflow .

Para casos complicados, recomendo começar primeiro em um diretório de trabalho "limpo", confirmando as alterações que você possui agora (em uma nova ramificação, se desejar). Dessa forma, o "lugar" em que você os está aplicando não tem mais nada e você estará apenas tentando as alterações ocultas:

git status               # see if there's anything you need to commit
                         # uh oh, there is - let's put it on a new temp branch
git checkout -b temp     # create new temp branch to save stuff
git add ...              # add (and/or remove) stuff as needed
git commit               # save first set of changes

Agora você está em um ponto de partida "limpo". Ou talvez seja mais assim:

git status               # see if there's anything you need to commit
                         # status says "nothing to commit"
git checkout -b temp     # optional: create new branch for "apply"
git stash apply          # apply stashed changes; see below about --index

O principal a lembrar é que o "stash" é um commit, é apenas um commit "engraçado / estranho" que não está "em um ramo". A applyoperação examina o que o commit mudou e tenta repeti-lo onde quer que você esteja agora. O estoque ainda estará lá ( applymantém-o por perto), para que você possa ver mais ou decidir que esse era o lugar errado applye tentar novamente de forma diferente ou o que quer que seja.


Sempre que você tiver um stash, poderá usar git stash show -ppara ver uma versão simplificada do que está no stash. (Esta versão simplificada examina apenas as alterações da "árvore de trabalho final", não as alterações de índice salvas que são --indexrestauradas separadamente.) O comando git stash apply, sem --index, apenas tenta fazer essas mesmas alterações no diretório de trabalho agora.

Isso é verdade mesmo se você já tiver algumas alterações. O applycomando tem prazer em aplicar uma ocultação a um diretório de trabalho modificado (ou pelo menos para tentar aplicá-lo). Você pode, por exemplo, fazer o seguinte:

git stash apply stash      # apply top of stash stack
git stash apply stash@{1}  # and mix in next stash stack entry too

Você pode escolher a ordem "aplicar" aqui, escolhendo stashes específicos para aplicar em uma sequência específica. Observe, no entanto, que cada vez que você está basicamente fazendo uma "mesclagem de git" e como a documentação de mescla adverte:

A execução do git merge com alterações não-triviais não confirmadas é desencorajada: enquanto possível, pode deixá-lo em um estado difícil de se recuperar no caso de um conflito.

Se você começar com um diretório limpo e fizer apenas várias git applyoperações, é fácil voltar atrás: use git reset --hardpara voltar ao estado limpo e alterar suas applyoperações. (É por isso que recomendo começar primeiro em um diretório de trabalho limpo, para esses casos complicados.)


E o pior caso possível?

Digamos que você esteja fazendo muitas coisas avançadas do Git, e tenha feito um stash, e queira git stash apply --index, mas não é mais possível aplicar o stash salvo --index, porque o ramo divergiu demais desde o momento em que você o salvou.

É para isso que git stash branchserve.

Se vocês:

  1. verifique o commit exato em que estava quando fez o original e stash, em seguida,
  2. crie um novo ramo e, finalmente,
  3. git stash apply --index

a tentativa de re-criar as mudanças definitivamente vai trabalhar. Isto é o que faz. (E depois elimina o stash desde que foi aplicado com êxito.)git stash branch newbranch


Algumas palavras finais sobre --index(o que diabos é isso?)

O que o --indexfaz é simples de explicar, mas um pouco complicado internamente:

  • Quando você tem alterações, é necessário git add(ou "estágio") antes da commiting.
  • Portanto, quando você executou git stash, pode ter editado os dois arquivos fooe zorg, mas apenas testado, um deles.
  • Portanto, quando você pede para recuperar o estoque, pode ser bom se forem git addas addcoisas ed e não git add as não adicionadas. Ou seja, se você addeditou, foomas não zorgvoltou antes de fazer stash, pode ser bom ter exatamente a mesma configuração. O que foi encenado, deve ser encenado novamente; o que foi modificado, mas não organizado, deve ser modificado novamente, mas não organizado.

A --indexbandeira para applytenta configurar as coisas dessa maneira. Se sua árvore de trabalho estiver limpa, isso geralmente funciona. Se sua árvore de trabalho já possui itens add, você pode ver como pode haver alguns problemas aqui. Se você deixar de fora --index, a applyoperação não tentará preservar toda a configuração em estágios / em estágios. Em vez disso, apenas invoca o mecanismo de mesclagem do git, usando o commit da árvore de trabalho no "stash bag" . Se você não se preocupa em preservar em estágios / não estágios, deixar de fora --indexfacilita muito a execução git stash apply.

torek
fonte
2
Eu não entendo o seu comentário. Você quer dizer: você correu git stash pop? Ou você quer dizer: você editou alguns arquivos, mas ainda não foi executado git stashnovamente? Ou você quer dizer algo completamente diferente?
torek
1
Sim. Observe que, na minha edição (longa), recomendo confirmar o que você tem agora antes de applyusar um stash. Você não precisa fazer isso, mas torna as coisas muito mais simples para você olhar. Você pode usar rebase -ipara agrupar várias confirmações ou escolher alterações específicas, ou o que for, posteriormente.
torek
1
Sim: git stash apply --index(lembre-se dos dois traços). Se você deixar de fora --index, não é grande coisa; o único ponto --indexé manter a configuração em estágios / não-estágios. (Você provavelmente não teve nenhuma configuração especial em primeiro lugar.) Então git statusetc, e adicione / confirme conforme desejado etc. Quando (e somente quando) tiver terminado o stash, use-o git stash droppara descartá-lo.
Torek
1
Contanto que você mantenha (não dropou pop) o stash, você sempre terá o código stash original seguro em uma confirmação, porque uma stash é uma confirmação! Se você deseja recuperá-lo exatamente, mas em um galho, use git stash branch(consulte a seção acima ou o livro Pro Git na resposta de Shunya ). Você pode, então, git checkoutesse ramo, ou git cherry-picka comprometer-off desse ramo, etc.
Torek
2
@ChuckWolber: As convenções de nomenclatura do Git deixam muito a desejar (quantos significados diferentes podemos atribuir às palavras "remote", "tracking" e "branch" ?!). Vale a pena notar que você pode aplicar um stash a algo não relacionado ao stash original.
torek 10/05/19
57
git stash pop

vai colocar tudo de volta no lugar

conforme sugerido nos comentários, você pode usar git stash branch newbranchpara aplicar o stash a uma nova ramificação, que é igual à execução:

git checkout -b newbranch
git stash pop
Stefano Falasca
fonte
Obrigado pela ajuda. Posso colocar essas alterações em uma nova ramificação? Agora eu estou em desenvolver ramo
Aswathy P Krishnan
3
O git stash branch newbranch cria um novo ramo com as alterações ocultas.
robert
3
@robert: git stash branch newbranchrealmente fará isso; mas lembre-se de que ele cria a nova ramificação com seu pai definido para o commit que estava HEADno momento em que stashfoi feito. Em outras palavras, é para quando você voltar depois de algum longa sessão de corte ou qualquer outra coisa, olhar para a bagunça, e decidir "Eu deveria ter colocado isso em um ramo, ao invés de stashing" :-)
Torek
Eu editei minha pergunta. Gostaria de obter essas alterações em um novo ramo, se possível.
Aswathy P Krishnan
1
Às vezes você apenas quer a resposta TLDR :)
sachinruk
24

Para simplificar, você tem duas opções para reaplicar seu estoque:

  1. git stash pop - Restaurar de volta ao estado salvo, mas exclui o stash do armazenamento temporário.
  2. git stash apply - Restaure de volta ao estado salvo e deixe a lista de stash para possível reutilização posterior.

Você pode ler com mais detalhes sobre git stashes neste artigo.

Nesha Zoric
fonte
19

Para verificar o seu conteúdo oculto: -

lista de stash git

aplique um stash específico não da lista de stash: -

git stash aplicar stash @ {2}

ou para aplicar apenas o primeiro esconderijo: -

git stash pop

Nota: o git stash pop removerá o stash da sua lista de stash, enquanto o git stash não será aplicado. Portanto, use-os de acordo.

Shivansh Rajolia - HeLleR
fonte
2

No mac, isso funcionou para mim:

lista de stash git (veja todos os seus stashs)

git stash list

git stash apply (apenas o número que você deseja da sua lista stash)

como isso:

git stash apply 1
Zack
fonte
0

você pode ocultar as alterações não confirmadas usando "git stash" e fazer check-out em uma nova ramificação usando "git checkout -b" e aplicar os commits stashed "git stash apply"

S.Sandeeptha
fonte