Todo mundo que usa Git já passou por um momento de pânico: um reset que apagou trabalho, um commit na branch errada, um push recusado, um conflito no meio de um rebase. A boa notícia é que o Git quase nunca perde nada de verdade, e quase toda enrascada tem um comando que resolve.

Este artigo é uma coleção de situações reais, organizadas por tema, cada uma com o comando exato e a explicação do que ele faz. No final há uma tabela completa para consulta rápida. Se você quer entender o Git a fundo, desde como ele funciona por dentro, leia antes o guia completo de Git e GitHub.

Desfazendo commits

Errei a mensagem do último commit

Bash
git commit --amend -m "Mensagem correta"

Substitui o último commit por um novo com a mensagem corrigida. Se ele já foi enviado, você vai precisar de git push --force-with-lease, e só faça isso se ninguém mais trabalha nessa branch.

Esqueci um arquivo no último commit

Bash
git add arquivo-esquecido.ts
git commit --amend --no-edit

Quero desfazer o último commit, mas manter as mudanças

Bash
git reset --soft HEAD~1

O commit some e as mudanças voltam para a staging area, prontas para um novo commit. Troque --soft por --mixed (ou omita) para que voltem para o working tree, sem estar preparadas.

Quero jogar fora os últimos commits locais

Bash
git reset --hard HEAD~2

Descarta os 2 últimos commits e as mudanças. Use só em commits que não foram enviados.

Preciso desfazer um commit que já está no GitHub

Bash
git revert a1b2c3d
git push

Cria um commit novo que faz o contrário do commit a1b2c3d. O histórico fica intacto, então é seguro em branches compartilhadas. Para reverter um commit de merge, indique qual pai manter: git revert -m 1 HASH_DO_MERGE.

Juntar os últimos commits em um só antes de abrir o PR

Bash
git reset --soft HEAD~3
git commit -m "feat: adiciona filtro por data"

Os 3 últimos commits viram um só. Para escolher commit a commit, use git rebase -i HEAD~3 e marque os que quer juntar com squash ou fixup.

Recuperando o que parecia perdido

Dei reset --hard e perdi commits

Bash
git reflog
Texto
e4f5a6b HEAD@{0}: reset: moving to HEAD~3
9c8d7e6 HEAD@{1}: commit: Implementa pagamento
Bash
git reset --hard 9c8d7e6

O reflog registra cada movimento do HEAD. O commit "apagado" continua no repositório; basta voltar para ele.

Apaguei uma branch por engano

Bash
git reflog | grep nome-da-branch     # ou procure o último commit dela
git branch nome-da-branch 9c8d7e6    # recria apontando para o commit

A mensagem do git branch -D também mostra o hash: Deleted branch feature (was 9c8d7e6).

Descartei um stash sem querer

Bash
git fsck --no-reflog | grep "dangling commit"
git show HASH                        # confira qual é o stash
git stash apply HASH

Stashes são commits; um stash descartado fica "solto" no repositório até a limpeza automática.

Recuperar um arquivo apagado em um commit antigo

Bash
git log --oneline -- caminho/arquivo.ts      # acha o commit que o apagou
git restore --source=HASH~1 caminho/arquivo.ts   # traz a versão anterior à remoção

Ver como um arquivo estava há 10 commits

Bash
git show HEAD~10:src/app.ts

Branches no lugar errado

Fiz commit na main em vez de numa branch

Bash
git branch feature/nova          # cria a branch no commit atual (leva o commit junto)
git reset --hard origin/main     # volta a main para o estado do remoto
git switch feature/nova

Fiz commit na branch errada (outra feature)

Bash
git switch branch-certa
git cherry-pick HASH             # copia o commit para cá
git switch branch-errada
git reset --hard HEAD~1          # remove de lá (se não foi enviado)

Comecei a mexer nos arquivos e preciso trocar de branch

Bash
git stash push -m "trabalho pela metade"
git switch outra-branch
# ... resolve o que precisava ...
git switch -
git stash pop

Ou leve as mudanças para uma branch nova direto: git switch -c nova-branch carrega as alterações não commitadas junto.

Renomear uma branch que já está no GitHub

Bash
git branch -m nome-antigo nome-novo
git push origin -u nome-novo
git push origin --delete nome-antigo

Limpar branches locais que já foram mescladas

Bash
git fetch --prune
git branch --merged main | grep -v " main$" | xargs git branch -d

No Windows, rode no Git Bash. -d recusa apagar o que não foi mesclado, o que dá uma camada de segurança.

Sincronizando com o remoto

O push foi recusado: "fetch first" ou "non-fast-forward"

Bash
git pull --rebase
git push

Alguém enviou commits antes de você. O pull --rebase baixa e reaplica os seus commits por cima, mantendo o histórico linear.

Quero descartar tudo e ficar igual ao GitHub

Bash
git fetch origin
git reset --hard origin/main
git clean -fd       # remove também arquivos não rastreados (confira antes com -n)

Fiz rebase e o push normal foi recusado

Bash
git push --force-with-lease

Diferente do --force, recusa o envio se alguém tiver enviado algo que você ainda não viu.

Atualizar minha branch com o que entrou na main

Bash
git switch minha-branch
git fetch origin
git rebase origin/main       # histórico linear (branch só sua)
# ou
git merge origin/main        # seguro em branch compartilhada

"refusing to merge unrelated histories"

Bash
git pull origin main --allow-unrelated-histories

Acontece quando o repositório do GitHub foi criado com README e o local foi iniciado separadamente.

Trocar o remoto de HTTPS para SSH

Bash
git remote set-url origin git@github.com:usuario/projeto.git
git remote -v

Conflitos

Ver quais arquivos estão em conflito

Bash
git status
git diff --name-only --diff-filter=U

Ficar com a minha versão (ou com a deles) em um arquivo inteiro

Bash
git checkout --ours caminho/arquivo      # versão da branch atual
git checkout --theirs caminho/arquivo    # versão da branch que está entrando
git add caminho/arquivo

Atenção: durante um rebase, os papéis se invertem (--ours é a base em que você está reaplicando).

Desistir do merge ou do rebase

Bash
git merge --abort
git rebase --abort
git cherry-pick --abort

Tudo volta ao estado anterior à operação.

Arquivos e .gitignore

Coloquei no .gitignore, mas o arquivo continua sendo rastreado

Bash
git rm --cached arquivo.env
git rm -r --cached pasta/
git commit -m "chore: para de rastrear arquivos ignorados"

Descartar todas as mudanças locais em arquivos rastreados

Bash
git restore .

Ver o que seria apagado antes de limpar arquivos não rastreados

Bash
git clean -n     # simula
git clean -fd    # apaga arquivos e pastas não rastreados
git clean -fdx   # inclui os ignorados (node_modules, builds...)

Desfazer mudanças em só um trecho de um arquivo

Bash
git restore -p arquivo.ts

O Git pergunta trecho por trecho o que descartar.

Investigando o histórico

Quem mudou esta linha e por quê?

Bash
git blame -L 40,60 src/pagamento.ts
git show HASH

Em qual commit esse texto apareceu ou sumiu?

Bash
git log -S "calculaFrete" --oneline

Achar o commit que introduziu um bug

Bash
git bisect start
git bisect bad
git bisect good v1.4.0
# teste cada commit sugerido e responda: git bisect good / git bisect bad
git bisect reset

Com um script de teste, automatize: git bisect run npm test.

O que eu fiz esta semana?

Bash
git log --author="$(git config user.email)" --since="1 week ago" --oneline

Segredos e arquivos grandes

Commitei uma senha ou token

O GitHub recusou um arquivo maior que 100 MB

Bash
git rm --cached arquivo-grande.zip
git commit --amend --no-edit     # se ele entrou no último commit

Se entrou em commits mais antigos, remova do histórico com o git filter-repo --path arquivo-grande.zip --invert-paths. Para versionar arquivos grandes, use o Git LFS (git lfs track "*.zip").

Tabela completa: Git em emergências

Cheat sheet

Git: comandos que salvam sua vida

Cada linha resolve uma situação real.

Desfazer commits

Do mais leve ao mais pesado

ComandoDescrição
git commit --amend -m "msg"Corrige a mensagem do último commit
git commit --amend --no-editInclui arquivo esquecido
git reset --soft HEAD~1Desfaz commit e mantém tudo preparado
git reset HEAD~1Desfaz commit e mantém no working tree
git reset --hard HEAD~1Desfaz commit e descarta mudanças
git revert HASHDesfaz commit já enviado
git revert -m 1 HASHDesfaz um commit de merge
git reset --soft HEAD~3Junta os 3 últimos commits

Recuperação

O Git quase nunca perde nada

ComandoDescrição
git reflogHistórico de onde o HEAD esteve
git reset --hard HEAD@{1}Volta para a posição anterior
git branch nome HASHRecria branch apagada
git fsck --no-reflogAcha commits soltos (stash perdido)
git restore --source=HASH arquivoTraz um arquivo de outro commit
git show HEAD~10:arquivoVê um arquivo no passado

Branches no lugar errado

Commits que foram parar onde não deviam

ComandoDescrição
git branch nova && git reset --hard origin/mainMove commits da main para branch nova
git cherry-pick HASHCopia um commit para a branch atual
git switch -c novaLeva mudanças não commitadas para nova branch
git stash / git stash popGuarda e recupera mudanças
git branch -m antigo novoRenomeia branch
git branch --merged mainBranches já mescladas

Remoto

Quando o GitHub não concorda com você

ComandoDescrição
git pull --rebaseResolve push recusado
git fetch && git reset --hard origin/mainFica igual ao remoto
git push --force-with-leaseForce push seguro
git rebase origin/mainAtualiza sua branch
git pull --allow-unrelated-historiesJunta históricos sem relação
git remote set-url origin URLTroca a URL do remoto
git fetch --pruneLimpa branches remotas apagadas

Conflitos

Quando duas mudanças se chocam

ComandoDescrição
git diff --name-only --diff-filter=UArquivos em conflito
git checkout --ours arquivoFica com a versão atual
git checkout --theirs arquivoFica com a versão que entra
git add arquivoMarca como resolvido
git merge --abortCancela o merge
git rebase --abortCancela o rebase
git rebase --continueSegue após resolver

Arquivos

Rastreamento e limpeza

ComandoDescrição
git rm --cached arquivoPara de rastrear e mantém o arquivo
git restore .Descarta mudanças locais
git restore -p arquivoDescarta trecho por trecho
git restore --staged arquivoTira da staging area
git clean -nSimula a limpeza
git clean -fdApaga não rastreados

Investigação

Quem, quando e por quê

ComandoDescrição
git blame -L 40,60 arquivoAutor de um trecho
git log -S "texto"Commits que mexeram no texto
git log --oneline --graph --allVisão geral do histórico
git bisect startCaça o commit do bug
git bisect run npm testBisect automático
git show HASH --statArquivos alterados num commit

Referências