Voltar para todos os artigos
Git Time Travel: reset, reflog, bisect e salvar branch zoada

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.

Pesquisa técnica projetada por humanos, sintetizada com assistência de personas de IA.
9 min de leitura

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 reflog recupera qualquer coisa que ainda existe. git reset reescreve histórico local. git revert desfaz coisas sem reescrever (seguro para histórico compartilhado). git bisect encontra 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 log padrão)
  • Como usar o reflog para recuperar tudo (ou quase tudo)
  • Quando usar reset vs revert (e como não virar o vilão do time)
  • Como caçar bugs com git bisect igual 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:

bash
git log --oneline --graph --decorate --all

Esse 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
bash
git reflog

Saída típica (simplificada):

bash
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:

bash
# Você foi emocionado git reset --hard HEAD~3

E agora?

  1. Veja o reflog:
bash
git reflog
  1. Encontre a entrada antes do reset — algo como:
bash
abcd123 HEAD@{3}: commit: Feature que você apagou
  1. Volte praquele commit criando uma branch de resgate:
bash
git checkout -b salvando-minha-vida abcd123

Pronto. Commit "apagado" ressuscitado.

2.2. Recuperei uma branch deletada

Você apagou a branch remota e local:

bash
git branch -D feature-top

Se você trabalhou nela recentemente, o commit final ainda vai aparecer no reflog.

  1. Procure por algo com o nome da branch ou o commit:
bash
git reflog --all | grep feature-top || git reflog --all | head -n 30
  1. Achou o commit? Crie uma branch nova em cima dele:
bash
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 usar git 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:

bash
# 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~1

Regra de ouro:

  • Use reset para reescrever histórico local.
  • Evite reset em 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.

bash
# Desfaz o último commit, criando outro commit git revert HEAD # Desfaz um commit específico git revert a1b2c3d

Perfeito para:

  • Corrigir cagadas já enviadas para o remoto
  • Desfazer merge ruim em main/master
bash
# 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 usar reflog).
  • Depois do push:
    • Prefira revert.
    • Use reset só se TODO MUNDO concordar em forçar o histórico (git push --force-with-lease).
bash
# Histórico já compartilhado? Seja adulto. # Em vez disso: git revert HEAD

Opinião polêmica: git push --force nã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

bash
# 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:
bash
git bisect bad
  • Se não aparece:
bash
git bisect good

Repete até o Git te dizer qual commit introduziu o bug.

Quando terminar:

bash
git bisect reset

4.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ê.

bash
# 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.sh

O 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:

  1. Não entre em desespero (sério).

  2. Rode:

    bash
    git status git log --oneline --graph --decorate --all -n 20 git reflog -n 20
  3. Identifique:

    • O que você quer voltar (commit, branch, merge)?
    • Esse histórico já foi pushed?
  4. Se for local apenas:

    • Use git reset (soft/mixed/hard, conforme o caso).
    • Se apagar demais, recupere com git reflog.
  5. Se já foi para o remoto:

    • Prefira git revert.
    • Discuta com o time antes de usar git push --force-with-lease.
  6. Se precisar achar o commit que introduziu o bug:

    • Use git bisect.

6. Aliases de dev raiz para time travel

Coloque isso no seu ~/.gitconfig para viver melhor:

ini
[alias] lg = log --oneline --graph --decorate --all undo-last = reset --soft HEAD~1 undo-hard = reset --hard HEAD~1 hist = reflog who-broke = bisect

Uso típico:

bash
# ver histórico bonito git lg # se arrepender do último commit (mantendo código) git undo-last # inspeção pós-desastre git hist

7. Resumão para colar na parede

  • git log --graph --decorate --all para entender o histórico.
  • git reflog para recuperar commits e branches "perdidos".
  • git reset para reescrever histórico local.
  • git revert para desfazer coisas em histórico compartilhado.
  • git bisect para 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

Receba novos artigos

Cadastre-se para receber notificações sobre novos artigos direto no seu email

Não enviaremos spam. Você pode cancelar a inscrição a qualquer momento.