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! ;)

LSDR.net

© 2004 - 09, Luiz Rocha

Todo conteúdo sob licenca Creative Commons by-sa, a não ser que explicitado.

As opiniões expressas nesse website não representam necessariamente a visão estratégica, as opiniões e posições do meu empregador, nem são endossadas pelo mesmo.

Caveat Lector