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
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
git add arquivo-esquecido.ts
git commit --amend --no-editQuero desfazer o último commit, mas manter as mudanças
git reset --soft HEAD~1O 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
git reset --hard HEAD~2Descarta 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
git revert a1b2c3d
git pushCria 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
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
git refloge4f5a6b HEAD@{0}: reset: moving to HEAD~3
9c8d7e6 HEAD@{1}: commit: Implementa pagamentogit reset --hard 9c8d7e6O reflog registra cada movimento do HEAD. O commit "apagado" continua no repositório; basta voltar para ele.
Apaguei uma branch por engano
git reflog | grep nome-da-branch # ou procure o último commit dela
git branch nome-da-branch 9c8d7e6 # recria apontando para o commitA mensagem do git branch -D também mostra o hash: Deleted branch feature (was 9c8d7e6).
Descartei um stash sem querer
git fsck --no-reflog | grep "dangling commit"
git show HASH # confira qual é o stash
git stash apply HASHStashes são commits; um stash descartado fica "solto" no repositório até a limpeza automática.
Recuperar um arquivo apagado em um commit antigo
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çãoVer como um arquivo estava há 10 commits
git show HEAD~10:src/app.tsBranches no lugar errado
Fiz commit na main em vez de numa branch
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/novaFiz commit na branch errada (outra feature)
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
git stash push -m "trabalho pela metade"
git switch outra-branch
# ... resolve o que precisava ...
git switch -
git stash popOu 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
git branch -m nome-antigo nome-novo
git push origin -u nome-novo
git push origin --delete nome-antigoLimpar branches locais que já foram mescladas
git fetch --prune
git branch --merged main | grep -v " main$" | xargs git branch -dNo 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"
git pull --rebase
git pushAlgué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
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
git push --force-with-leaseDiferente 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
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"
git pull origin main --allow-unrelated-historiesAcontece quando o repositório do GitHub foi criado com README e o local foi iniciado separadamente.
Trocar o remoto de HTTPS para SSH
git remote set-url origin git@github.com:usuario/projeto.git
git remote -vConflitos
Ver quais arquivos estão em conflito
git status
git diff --name-only --diff-filter=UFicar com a minha versão (ou com a deles) em um arquivo inteiro
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/arquivoAtenção: durante um rebase, os papéis se invertem (--ours é a base em que você está reaplicando).
Desistir do merge ou do rebase
git merge --abort
git rebase --abort
git cherry-pick --abortTudo volta ao estado anterior à operação.
Arquivos e .gitignore
Coloquei no .gitignore, mas o arquivo continua sendo rastreado
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
git restore .Ver o que seria apagado antes de limpar arquivos não rastreados
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
git restore -p arquivo.tsO Git pergunta trecho por trecho o que descartar.
Investigando o histórico
Quem mudou esta linha e por quê?
git blame -L 40,60 src/pagamento.ts
git show HASHEm qual commit esse texto apareceu ou sumiu?
git log -S "calculaFrete" --onelineAchar o commit que introduziu um bug
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 resetCom um script de teste, automatize: git bisect run npm test.
O que eu fiz esta semana?
git log --author="$(git config user.email)" --since="1 week ago" --onelineSegredos e arquivos grandes
Commitei uma senha ou token
O GitHub recusou um arquivo maior que 100 MB
git rm --cached arquivo-grande.zip
git commit --amend --no-edit # se ele entrou no último commitSe 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
Git: comandos que salvam sua vida
Cada linha resolve uma situação real.
Desfazer commits
Do mais leve ao mais pesado
Recuperação
O Git quase nunca perde nada
Branches no lugar errado
Commits que foram parar onde não deviam
Remoto
Quando o GitHub não concorda com você
Conflitos
Quando duas mudanças se chocam
Arquivos
Rastreamento e limpeza
Investigação
Quem, quando e por quê
Referências
- Oh Shit, Git!?!: a inspiração de muitas dessas receitas.
- Pro Git em português: o livro oficial, gratuito.
- Documentação de referência do Git: todos os comandos e opções.
- git-filter-repo: para reescrever o histórico com segurança.



