
Git Time Travel: reset, reflog, bisect e salvar branch zoada
Aprenda a viajar no tempo com o Git: reflog, reset, revert, bisect e técnicas para desfazer desastres sem derrubar o time.
✨TL;DR / Sumário Executivo
Aprenda a viajar no tempo com o Git: reflog, reset, revert, bisect e técnicas para desfazer desastres sem derrubar o time.
💡 TL;DR (Resumo)
Git permite viajar no tempo e consertar erros.
git reflogrecupera qualquer coisa que ainda existe.git resetreescreve histórico local.git revertdesfaz coisas sem reescrever (seguro para histórico compartilhado).git bisectencontra o commit que quebrou tudo automaticamente. Use essas ferramentas com confiança — o Git foi feito pra isso.
Todo dev que usa Git o suficiente acaba cometendo o clássico: git push errado, branch apagada, commit em branch errada, bug que "apareceu do nada" depois de um merge.
A diferença entre o dev sofrido e o dev raiz é simples: o dev raiz sabe viajar no tempo com o Git.
Neste artigo, vamos sair do básico (git log, git reset --hard, esses perigos) e entrar no que realmente separa adultos de crianças no Git:
- Como enxergar o histórico de verdade (não só o
git logpadrão) - Como usar o reflog para recuperar tudo (ou quase tudo)
- Quando usar
resetvsrevert(e como não virar o vilão do time) - Como caçar bugs com
git bisectigual gente grande - Um kit de sobrevivência para desastres em produção
No fim, você vai conseguir quebrar coisas com confiança — porque sabe voltar atrás.
1. Entendendo o tempo no Git (sem filosofia barata)
Antes de sair tacando reset --hard, você precisa de uma imagem mental decente do que o Git está fazendo.
1.1. Commits, refs e o tal do HEAD
Simplificando bastante:
- Cada commit é um snapshot do projeto.
- Branches (
main,develop, etc.) são ponteiros para commits. HEADé "onde você está" agora — normalmente apontando para uma branch.
Confira isso na prática:
git log --oneline --graph --decorate --allEsse comando mostra:
- O grafo de commits (
--graph) - Todas as refs (branches, tags,
HEAD) (--decorate --all)
Use isso todo dia. Dev que só usa git log seco está jogando no fácil.
1.2. O que realmente significa "perder" um commit
Na maioria das vezes você não perdeu nada. Você só tirou a referência para aquele commit.
Enquanto o Git ainda lembra desse commit em algum lugar (spoiler: reflog), dá pra resgatar.
2. git reflog: o histórico secreto que salva sua carreira
git log mostra o histórico de commits.
git reflog mostra o histórico de movimentos do HEAD.
Ou seja, tudo que você fez:
- Checkout de branch
- Reset
- Merge
- Rebase
- Commit
- Pulando de branch em branch igual louco
git reflogSaída típica (simplificada):
1a2b3c4 (HEAD -> main) HEAD@{0}: commit: Ajusta log de erro
9f8e7d6 HEAD@{1}: reset: moving to HEAD~1
abcd123 HEAD@{2}: commit: Remove código legado
...Cada linha é um "frame" da sua viagem no tempo.
2.1. Recuperei um commit apagado sem querer
Cenário clássico:
# Você foi emocionado
git reset --hard HEAD~3E agora?
- Veja o reflog:
git reflog- Encontre a entrada antes do reset — algo como:
abcd123 HEAD@{3}: commit: Feature que você apagou- Volte praquele commit criando uma branch de resgate:
git checkout -b salvando-minha-vida abcd123Pronto. Commit "apagado" ressuscitado.
2.2. Recuperei uma branch deletada
Você apagou a branch remota e local:
git branch -D feature-topSe você trabalhou nela recentemente, o commit final ainda vai aparecer no reflog.
- Procure por algo com o nome da branch ou o commit:
git reflog --all | grep feature-top || git reflog --all | head -n 30- Achou o commit? Crie uma branch nova em cima dele:
git checkout -b feature-top-v2 <hash-do-commit>Reflog é basicamente o Ctrl+Z estendido do Git.
Use sem medo — ele é só leitura.
Controvérsia dev raiz: se você não sabe usar
git reflog, você não está pronto pra usargit reset --hard.
3. git reset vs git revert: quando apagar, quando desfazer
Esses dois comandos confundem até sênior. Bora deixar claro.
3.1. git reset
reset mexe em ponteiros e, dependendo do modo, no seu working directory.
Três modos principais:
--soft: só mexe no ponteiro da branch; deixa as mudanças na área de stage.--mixed(padrão): mexe no ponteiro e tira arquivos do stage, mas mantém no working directory.--hard: volta tudo — ponteiro, stage e arquivos.
Exemplos:
# Volta 1 commit, mantendo alterações no stage
git reset --soft HEAD~1
# Volta 1 commit, mantendo alterações como modificações locais (unstaged)
git reset HEAD~1
# Volta 1 commit, jogando código fora mesmo
git reset --hard HEAD~1Regra de ouro:
- Use
resetpara reescrever histórico local. - Evite
resetem branches já compartilhadas (push feito).
3.2. git revert
revert não apaga o commit. Ele cria um novo commit que desfaz as mudanças de outro.
# Desfaz o último commit, criando outro commit
git revert HEAD
# Desfaz um commit específico
git revert a1b2c3dPerfeito para:
- Corrigir cagadas já enviadas para o remoto
- Desfazer merge ruim em
main/master
# Desfaz um merge específico
git revert -m 1 <hash-do-merge>-m 1 indica qual "lado" do merge é o principal (normalmente o branch de destino, tipo main).
3.3. Guia rápido: quando usar o quê
- Trabalhando sozinho, antes do push: pode usar
resetà vontade (mas saiba usarreflog). - Depois do push:
- Prefira
revert. - Use
resetsó se TODO MUNDO concordar em forçar o histórico (git push --force-with-lease).
- Prefira
# Histórico já compartilhado? Seja adulto.
# Em vez disso:
git revert HEADOpinião polêmica:
git push --forcenão é errado. Errado é usar sem entender o que está reescrevendo.
4. Caçando bugs com git bisect (modo sniper)
Sabe aquele bug que "sempre funcionou" e parou em algum momento do passado?
Você pode ficar chutando commits… ou pode usar git bisect e achar o culpado em O(log n) passos.
4.1. Conceito
Você precisa de duas coisas:
- Um commit bom (onde o bug não existia)
- Um commit ruim (onde o bug existe)
O Git vai testando o meio do caminho até achar o primeiro commit ruim.
4.2. Modo manual
# Inicia o bisect
git bisect start
# Marca o commit atual como ruim
git bisect bad
# Marca um commit antigo como bom
git bisect good <hash-ou-tag>O Git vai te jogar em um commit intermediário.
Você testa o sistema:
- Se o bug aparece:
git bisect bad- Se não aparece:
git bisect goodRepete até o Git te dizer qual commit introduziu o bug.
Quando terminar:
git bisect reset4.3. Modo automático (pra dev preguiçoso inteligente)
Se você consegue automatizar o teste (script que retorna 0 para bom e 1 para ruim), o Git faz tudo pra você.
# Exemplo de script tosco de teste
cat << 'EOF' > test-bug.sh
#!/usr/bin/env bash
# roda testes, lints, ou o que comprova a existência do bug
npm test > /dev/null 2>&1
EOF
chmod +x test-bug.sh
# Agora roda o bisect automatizado
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
git bisect run ./test-bug.shO Git vai pulando commits sozinho.
Esse é o tipo de coisa que parece overkill… até você ter um bug bizarro em produção.
5. Checklist de sobrevivência para desastres Git
Quando der ruim, em vez de entrar em pânico, siga essa sequência:
-
Não entre em desespero (sério).
-
Rode:
bashgit status git log --oneline --graph --decorate --all -n 20 git reflog -n 20 -
Identifique:
- O que você quer voltar (commit, branch, merge)?
- Esse histórico já foi pushed?
-
Se for local apenas:
- Use
git reset(soft/mixed/hard, conforme o caso). - Se apagar demais, recupere com
git reflog.
- Use
-
Se já foi para o remoto:
- Prefira
git revert. - Discuta com o time antes de usar
git push --force-with-lease.
- Prefira
-
Se precisar achar o commit que introduziu o bug:
- Use
git bisect.
- Use
6. Aliases de dev raiz para time travel
Coloque isso no seu ~/.gitconfig para viver melhor:
[alias]
lg = log --oneline --graph --decorate --all
undo-last = reset --soft HEAD~1
undo-hard = reset --hard HEAD~1
hist = reflog
who-broke = bisectUso típico:
# ver histórico bonito
git lg
# se arrepender do último commit (mantendo código)
git undo-last
# inspeção pós-desastre
git hist7. Resumão para colar na parede
git log --graph --decorate --allpara entender o histórico.git reflogpara recuperar commits e branches "perdidos".git resetpara reescrever histórico local.git revertpara desfazer coisas em histórico compartilhado.git bisectpara achar o commit que trouxe o bug.
Use o Git como máquina do tempo, não como roleta russa.
Se curtiu esse mergulho mais hardcore em Git, compartilha com aquele amigo que ainda tem medo de git reset.
Me encontra no X/Twitter: @gss_62
#git #gittips