CLI AI

Remover uma senha do histórico do git

2026-06-01

Remover uma senha do histórico do git significa reescrever os commits que a contêm com git filter-repo --invert-paths --path <file>, e depois expirar o reflog e rodar o garbage collection para que os commits antigos também desapareçam do .git. Faça isso só depois de rotacionar a chave — um segredo vazado é considerado comprometido no momento do commit, independentemente de você limpar o histórico depois. .gitignore e git rm --cached não têm efeito nenhum sobre commits que já existem.

1. Confirme se o segredo ainda está no histórico

clai
$ clai verifique se essa chave ainda está em algum lugar do histórico do repositório→ git log --all --oneline -S 'sk-live-abc123secret'0fb8c94 stop tracking .env4c1d9ff add app and env

-S encontra commits em que o número de ocorrências dessa string mudou — ou seja, onde o segredo foi adicionado e onde foi removido. A busca cobre todo o histórico de todas as branches, não a árvore de trabalho.

2. Confirme que remover do índice não resolveu

clai
$ clai pegue o arquivo .env do commit em que ele foi adicionado→ git show 4c1d9ff:.envAPI_KEY=sk-live-abc123secret

Esse é todo o problema num único comando. O .env sumiu da árvore de trabalho, está no .gitignore, e o git rm --cached já rodou — mesmo assim, qualquer pessoa com um clone consegue tirar o segredo com um único comando. O commit ainda guarda o conteúdo completo.

3. Veja em quais commits o caminho aparece

clai
$ clai mostre todos os commits que mencionam o arquivo .env→ git log --all --oneline -- .env0fb8c94 stop tracking .env4c1d9ff add app and env

Essa é a lista do que precisa ser reescrito. Dois commits e você se livra fácil. Duzentos espalhados por várias branches e primeiro é preciso combinar com o time inteiro.

4. Primeiro rotacione, depois limpe

Um segredo que entrou no git tem que ser tratado como vazado, sem exceção. O repositório pode já ter sido clonado, forkado, indexado por um bot ou cacheado pelo CI antes mesmo de você notar o erro. Revogue a chave e emita uma nova antes de mexer no histórico: um histórico limpo com uma chave roubada ainda ativa é pior do que um histórico bagunçado com uma chave já revogada.

5. Reescreva o histórico com a ferramenta certa

clai
$ clai remova o arquivo .env de todo o histórico do repositório→ git filter-repo --invert-paths --path .env⚠ DANGER — rewrites all history, every commit hash changes

git filter-repo é o que o próprio projeto git recomenda. git filter-branch está obsoleto: é ordens de magnitude mais lento e pode corromper o repositório silenciosamente se usado sem cuidado. O BFG Repo-Cleaner é a outra opção: mais rápido em repositórios grandes, e consegue substituir uma string por ***REMOVED*** em vez de apagar o arquivo inteiro.

6. Limpe o que sobrou localmente

clai
$ clai expire as referências antigas e rode o garbage collection de forma agressiva→ git reflog expire --expire=now --all && git gc --prune=now --aggressive

Depois da reescrita, os commits antigos continuam alcançáveis pelo reflog — ou seja, o segredo ainda está dentro do .git. Esse comando os remove de vez. No GitHub ou GitLab, você ainda vai precisar pedir ao suporte que limpe o cache deles, e dos forks ninguém cuida por você.

Pegadinhas

  • Um histórico reescrito quebra todos os clones do time. Depois do force-push, cada um vai precisar clonar de novo ou fazer git rebase --onto. Avise com antecedência, ou alguém vai acabar empurrando o histórico antigo de volta.
  • Forks e pull requests sobrevivem. No GitHub, um commit de um PR fechado pode continuar acessível por link direto mesmo depois de limpar o repositório principal. Mais um motivo para rotacionar a chave.
  • git filter-branch está obsoleto. O próprio git imprime um aviso e aponta para o filter-repo quando você o executa. Metade dos artigos bem ranqueados ainda não sabe disso.

Perguntas relacionadas

Basta adicionar o arquivo ao .gitignore? Não. O .gitignore só afeta arquivos novos. Tudo que já foi commitado permanece por inteiro no histórico.

Como evito que isso aconteça de novo? Um hook de pre-commit com um scanner de segredos: gitleaks, detect-secrets ou trufflehog. Eles pegam a chave antes do commit, não depois que ela já está pública.

E se o segredo já estiver no GitHub? Revogue a chave imediatamente, depois limpe o histórico, depois peça ao suporte do GitHub para limpar as visualizações em cache. É essa a ordem.

Veja também

O CliAI marca git filter-repo como DANGER e pede confirmação digitada antes de tocar em um único commit. Instale em uma linha.