git-stash
Como o uso diário do git, algumas funcionalidades bacanas começam a saltar aos olhos. Uma que está rapidamente se tornando favorita é o git-stash.
O git-stash funciona quase como um branch “anônimo” no seu repositório local. Ao executar um git stash (ou git stash save), todo conteúdo vivo do seu repositório local é salvo em .git/refs/stash e o repositório é resetado para o HEAD, retornando ao estado limpo, antes de se fazer qualquer alteração.
Com o git stash show é possível ver as mudancas, como um diff, entre as alterações salvas e o código corrente. Coincidência ou não, o git stash show aceita as opções do git-diff.
O código pode ser reintegrado ao repositório utilizando git stash apply, no qual é possível passar para o comando qual stash deseja aplicar no repositório. O mesmo pode ser obtido através do git stash pop. A principal diferença entre o apply e o pop é que o segundo limpa o registro do stash, enquanto o primeiro aplica as modificações salvas no repositório mas mantém o material salvo no stash.
Tudo que foi guardado no stash pode ser visto utilizando o git stash list. Alterações salvas no stash podem ser removidas utilizando o git stash drop mais o índice do stash ou usando o git stash clear para limpar tudo.
Resumo da ópera
Em resumo, o workflow de uso do git-stash é, de maneira bastante simplificada:
1 - Para salvar o alterações no repositório local em um branch “anônimo”:
$ git stash
Saved working directory and index state "WIP on branch-test-01: 2897277... changing the way the api behaves"
HEAD is now at 2897277 accidentally removed the routing, but fear not, they're back now
2 - Para listar stashs existentes:
$ git stash list
stash@{1}: WIP on branch-test-01: 2345672... added PUT/DELETE support
stash@{0}: WIP on branch-test-01: 2897277... changing the way the api behaves
3 - Aplicando o conteúdo do stash de volta ao repositório:
$ git stash apply
# On branch branch-test-01
# Changed but not updated:
# (use "git add ..." to update what will be committed)
#
# modified: api/__init__.py
#
no changes added to commit (use "git add" and/or "git commit -a")
4 - Visualizando a diferença entre o código corrente e último stash:
$ git stash show
api/__init__.py | 16 ++++++++--------
1 files changed, 8 insertions(+), 8 deletions(-)
Usando git stash show -u mostra todo o diff, similar a um diff -u arquivo1 arquivo2.
5 - Removendo um stash específico, passando o índice do mesmo:
$ git stash drop stash@{1}
Dropped stash@{1} (c9d2bd17f3e1121daaf0e865a53dbad8610d70b2)
Lembrando que a utilização do git stash pop aplica e remove o stash da lista.
Comentários finais
Essas facilidades são muito uteis quando se está testando abordagens para a solução de um problema. Muito útil também quando se está trabalhando com uma base de código grande, bastante elaborada e pouco conhecida, onde passear um pouco e brincar é um excelente exercício de aprendizado.
O bazaar-ng e o mercurial tem soluções similares, ambas chamadas shelf. O lado negativo é que, pelo menos até onde eu pesquisei, ambas são implementações externas (plugins), enquanto o git vem com o stash por padrão.
Comentário de Felipe Diesel - 29.09.08 @ 14h17 #
Muito bom mesmo essa funcionalidade, mas eu não conhecia. Parece ser muito boa para aquelas horas em que você está desenvolvendo algo novo e a casa cai e tem que ser corrigido algo urgentemente!