Não é incomum nos depararmos com a necessidade de remoção de arquivos indesejáveis que foram parar em algum commit no seu repositório Git. Pode ser um arquivo executável sujando seu histórico, ou podem ser arquivos de dados ou de configuração com informações sensíveis.

Há pouco tempo era difícil tratar este tipo de situação. Agora temos ferramentas modernas e eficientes pra nos salvar.

Uma delas é o git-filter-repo. Uma ferramenta de linha de comando para reconstrução do repositório baseada em filtro.

Para instalar podemos usar o pip, um gerenciador de pacotes do Python que é ferramenta cada vez mais presente nos ambientes de desenvolvimento.

pip install git-filter-repo

O git-filter-repo trabalha com um repositório limpo, de preferência recém clonado. É arriscado usar na sua pasta de trabalho pois ele pode fazer um reset sem cerimônia, e arquivos de trabalho importantes serão perdidos.

Faça um clone ou uma cópia limpa do repositório.

Na pasta do clone, supondo que você queira eliminar todos os arquivos .exe, dispare o comando git filter-repo com o filtro.

git filter-repo --path-glob '*.exe' --invert-paths

A ferramenta vai fazer o "trabalho sujo" e deixar o repositório brilhando.

O git filter-repo analisará todo o histórico e removerá as referências ao(s) arquivo(s) especificado(s). Ele também faz uma limpeza automática (como git gc).

NOTICE: Removing 'origin' remote; see 'Why is my origin removed?'
        in the manual if you want to push back there.
        (was ...)
Parsed 43 commits
New history written in 0.43 seconds; now repacking/cleaning...
Repacking your repo and cleaning out old unneeded objects

Adicione ao .gitignore para prevenir futuros commits.

Crie ou edite o arquivo .gitignore na raiz do seu repositório e adicione uma linha *.exe para ignorar os arquivos.

git add .gitignore
git commit -m "Adiciona .exe ao gitignore"

Envie as alterações para o repositório remoto. Como você reescreveu o histórico, um git push normal provavelmente não vai rolar. Você precisará forçar o push.

Forçar o push (--force ou --force-with-lease) sobrescreve o histórico no repositório remoto. Avise todos os colaboradores antes de fazer isso, pois eles precisarão atualizar seus clones locais de maneira especial (geralmente fazendo fetch e reset).

git push origin nome-da-sua-branch --force

E é isso.

Lembre-se sempre do backup e da comunicação com a equipe ao reescrever o histórico.