git-stash vs. git-branch

92

Em uma pergunta anterior do Git , Daniel Benamy estava falando sobre um fluxo de trabalho no Git:

Eu estava trabalhando no master e comprometi algumas coisas e então decidi que queria colocar esse trabalho em espera. Fiz backup de alguns commits e depois ramifiquei antes de começar meu trabalho de merda.

Ele queria restaurar seu estado de funcionamento a um ponto anterior no tempo sem perder as alterações atuais. Todas as respostas giravam em torno, de várias maneiras, algo como

git branch -m master crap_work
git branch -m previous_master master

Como isso se compara a git stash? Estou um pouco confuso tentando ver qual é o caso de uso diferente aqui, quando parece que tudo git stashjá está resolvido por ramificação ...


@ Jordi Bunster : Obrigado, isso esclarece as coisas. Acho que consideraria "esconder" como um galho leve e sem nome. Portanto, qualquer coisa que o stash pode fazer, o branch também pode, mas com mais palavras. Agradável!

Will Robertson
fonte

Respostas:

109

'stash' pega as coisas não comprometidas e " sujas " em sua cópia de trabalho e as esconde, deixando você com uma cópia de trabalho limpa.

Ele realmente não se ramifica. Você pode então aplicar o stash em cima de qualquer outro branch. Ou, a partir do Git 1.6, você pode fazer:

git stash branch <branchname> [<stash>]

para aplicar o stash no topo de um novo branch, tudo em um comando.

Portanto, o stash funciona muito bem se você ainda não se comprometeu com o branch " errado ".

Se você já se comprometeu, o fluxo de trabalho que você descreve em sua pergunta é uma alternativa melhor. E, a propósito, você está certo: o Git é muito flexível, e com essa flexibilidade vem a sobreposição de funcionalidades.

Jordi Bunster
fonte
1
uma coisa que me incomoda ... você pode escrever como um [<stash>] realmente se parece! Eles o colocam nessa notação nos documentos, mas não é óbvio se deveria ser 1 ou @ {1} ou o quê.
Gregg Lind
1
Se você quiser se referir a um estoque "N" específico, use stash @ {N}
Jordi Bunster
9
Veja git stash listos nomes dos seus esconderijos.
idbrii
6
Gregg, sim, você pode: git stash save (nome do seu stash). Torna-se muito mais útil se você usá-lo muito para saber o que cada esconderijo faz. Você pode usar git stash show -p (nome) para mostrar o patch de um stash.
Thomas Vander Stichele,
7
também, git stash show -upara mostrar uma diferença do stash contra a cópia de trabalho.
ken
49

Quando você restaura seu stash, suas alterações são reaplicadas e você continua trabalhando em seu código.

Para esconder suas mudanças atuais

$ git stash save 
Saved "WIP on master: e71813e..."

Você também pode ter mais de um estoque. O estoque funciona como uma pilha. Cada vez que você salva um novo estoque, ele é colocado no topo da pilha.

$ git stash list
stash@{0}: WIP on master: e71813e..."

Observe a stash@{0}parte? Essa é a sua ID secreta. Você precisará dele para restaurá-lo mais tarde. Vamos fazer isso agora. O ID do estoque muda com cada estoque que você faz. stash @ {0} refere-se ao último stash que você fez.

Para aplicar um esconderijo

$ git stash apply stash@{0}

Você pode notar que o stash ainda está lá depois de aplicá-lo. Você pode largá-lo se não precisar mais dele.

$ git stash drop stash@{0}

Ou, como o estoque funciona como uma pilha, você pode retirar o último estoque que salvou:

$ git stash pop

Se você quiser limpar todos os seus esconderijos, execute o comando 'clear':

$ git stash clear

Pode muito bem ser que você não use esconderijos com tanta frequência. Se você deseja apenas armazenar suas alterações rapidamente para restaurá-las mais tarde, pode deixar de fora o ID de armazenamento.

$ git stash
...
$ git stash pop

Sinta-se à vontade para experimentar o estoque antes de usá-lo em algum trabalho realmente importante.

Eu também tenho uma versão mais detalhada disso postada no meu blog .

Ariejan
fonte
recurso muito mais útil do que a suposta 'melhor' resposta ... (embora a melhor resposta tenha
deixado
9

Sempre fico cauteloso com o git stash. Se você esconder algumas vezes, as coisas tendem a ficar confusas. git stash list exibirá uma lista numerada de stashes que você criou, com mensagens se você os forneceu ... Mas o problema está no fato de que você não pode limpar stashes, exceto com um git stash clear brutal (que remove todos) . Então, a menos que você seja sempre anal em dar mensagens superdescritivas para seus stashes (meio que vai contra a filosofia do stash), você acaba com um monte de stashes incompreensível.

A única maneira que conheço de descobrir qual é usar gitk --all e localizar os stashes. Pelo menos isso permite que você veja em que commit o stash foi criado, bem como o diff de tudo incluído naquele stash.

Observe que estou usando git 1.5.4.3 e acho que 1.6 adiciona git stash pop, que acho que aplicaria o stash selecionado e removeria da lista. O que parece muito mais limpo.

Por enquanto, sempre tento ramificar, a menos que tenha certeza absoluta de que voltarei a esse estoque no mesmo dia, mesmo dentro de uma hora.

webmat
fonte
3
Você faz ramos sem dar-lhes nomes úteis? Se não, então não vejo por que você não faz o mesmo com o estoque. Se você realmente deseja saber o que eles contêm, basta usar git-stash show para mostrar quais arquivos foram alterados ou git-stash apply e git-diff para ver os diffs reais. Manter o estoque reduzido é o mesmo que manter seus galhos sob controle.
Xiong Chiamiov
18
na verdade, você pode excluir um único estoque usandogit stash drop [<stash>]
kumarharsh
1
Verdade, git teve o git stash suspenso por um longo tempo. É muito menos um PITA de usar agora. Eu o uso todos os dias, e mesmo em longos períodos de tempo, agora.
webmat
3

Se você estiver procurando por um fluxo de trabalho que pode ser mais adequado do que git stash, você pode querer dar uma olhada em git-bottle . É um utilitário com o propósito de salvar e restaurar os vários estados de trabalho git como commits normais do git, efetivamente fazendo um instantâneo do estado atual e pertinente de sua árvore de trabalho e todos vários estados de arquivo mostrados sob o status do git.

Principais diferenças de git stash:

  • git stashsalva o estado sujo do git de forma restrita (arquivos modificados e arquivos adicionados ao índice), ao passo que git-bottleé projetado para salvar tudo o que é diferente de HEAD, e diferencia de forma preservada entre modificados, modificados e não adicionados, não adicionados, caminhos não mesclados, e os estados de rebase / mesclagem completos (apenas os caminhos abaixo .gitignorenão são salvos).
  • git stashsalva para esconder objetos que você precisa controlar separadamente. Se eu escondi algo 2 semanas atrás, posso não me lembrar, enquanto git-bottlesalva como tentativas de confirmação para o branch atual . A ação reversa é git-unbottleequivalente ao git stashpop. É possível enviar e compartilhar esses commits entre os repositórios. Isso pode ser útil para construções remotas, onde você tem outro repositório em um servidor remoto apenas para construção ou para colaborar com outras pessoas na resolução de conflitos.
Dan Aloni
fonte