26/01/2022

Meu GIT está com um "lixo"!

Um projeto Django iniciado para ter várias visualizações de dados de um ERP, acabou sendo utilizado também como um site de publicações de um setor da empresa.

Trabalhar nas rotinas voltadas para dados era sempre muito mais complexo que nas tais publicações, além de geralmente serem mais urgentes, por poderem ter impacto, por exemplo, no controle da produção.

Assim, quando me pediam para publicar algo, eu tinha que resolver da forma mais simples possível, para não tomar muito tempo.

Nisso de precisar soluções rápidas, certo dia adicionei uma imagem ao repositório, apenas porque naquele momento era a forma mais rápida de resolver o problema. Do repositório a imagem foi para o servidor em produção e pronto. Tá lá a publicação.

Tudo lindo! Bola pra frente! Vida que segue!

Porém, eu sabia que aquela imagem não deveria ter ido para o repositório.

"Tudo bem," - pensei - "assim que der, resolvo isso."

Resolvi? Não.

Aconteceu situação similar dias depois? Sim.

E depois e depois e depois...

Agora, com um repositório gordo de tantas ingestões indevidas, resolvi dar um basta.


Apesar de usar Git há muito tempo, não sou um daqueles poucos que domina todas as possíveis manobras dessa ferramenta.

Ao procurar como resolver o problema:

  • percebi que não é um problema só meu.
    • Ainda bem! Afinal, assim já tinha "muito stackoverflow" sobre isso.
  • descobri que existem muitas possíveis soluções.

Quanto aos casos semelhantes ou equivalentes, geralmente os motivos não são tão vergonhosos como os meu caso. Relatos que encontrei falavam, por exemplo, de adição indevida de um grande log, que é descoberto depois de vários outros commits.

Depois de ler sobre as diversas soluções, descobri a mais recomendada e... Mãos à obra!

Opa! Por mais documentada, garantida, eficiente, etc. que seja a solução, não dá para fazer novo, para mim, direto no repositório do projeto.

Então decidi, não apenas criar um repositório para fazer esse teste, mas também documentar o processo neste post.

Por preciosismo resolvi que não bastava testar incluindo e excluindo arquivos no repositório de teste.

Eu queria testar com um projeto mínimo funcional, para ver se, depois do necessário rebase do repositório em produção, a aplicação continuaria funcionando.

Por "projeto mínimo funcional" eu criei um "mínimo" mesmo!

Um projeto é um Flash 2, rodando com Python 3.8, com apenas uma rota, que responde "Oi, mundo!".

Link do repositório: https://github.com/anselmobd/git-filter-repo-test

No README.md do repositório tem um passo a passo para verificar o funcionamento da super-aplicação de "Oi, mundo!"

Este diretório é o equivalente ao meu diretório de desenvolvimento do projeto.

Depois de tudo funcionando, comecei o teste de remoção do lixo pelo início:

Adicionando lixo ao repositório

Antes dei uma conferida no tamanho do projeto, desconsiderando o tamanho do diretório local do repositório.

du -sh --exclude ".git/*"

28K    .

Então baixei uma logo do Python com 500 Kb do site LogoDownload, salvando no diretório local do projeto.

Adicionei a imagem ao repositório.

git add python-logo.png

git commit -m "carga indevida"

[main c8efab0] carga indevida
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 python-logo.png

Verifiquei novamente o tamanho do projeto.

du -sh --exclude ".git/*"

544K    .

Exatamente o que eu queria: Extremamente pesado, para um "Oi, mundo".

Criando commits extras, para simular minimamente o que ocorreu no meu projeto real:

No arquivo "hello.py" alterei "Oi, mundo!" para "Oi, python!". Então:

git add hello.py

git commit -m "oi python"

[main a1c2747] oi python
 1 file changed, 1 insertion(+), 1 deletion(-)

No mesmo arquivo, voltei a mensagem para "Oi, mundo!", e:

git add hello.py

git commit -m "oi mundo"

[main 1210137] oi mundo
 1 file changed, 1 insertion(+), 1 deletion(-)

Implantantando a aplicação em um servidor, seguindo os mesmos passos descritos no teste inicial

Segui, lá também, os passos descritos no README.md.

Tudo funcionando!

Iniciando o procedimento com git-filter-repo

Segui os dados descritos no install do repositório newren/git-filter-repo.

pip3 install git-filter-repo

Depois executei o comando que retira totalmente a imagem indevida do projeto. Inclusive do histórico de commits do projeto.

git filter-repo --path python-logo.png --invert-paths

Aborting: Refusing to destructively overwrite repo history since
this does not look like a fresh clone.
  (expected at most one entry in the reflog for HEAD)
Please operate on a fresh clone instead.  If you want to proceed
anyway, use --force.

Ops! Problema!

A mensagem informa que o ideal é trabalhar em um fresh clone, não neste repositório local de desenvolvimento.

Então, em outro diretório crie o necessário fresh clone do projeto:

cd ..
mkdir fresh_clone
cd fresh_clone
git clone https://github.com/anselmobd/git-filter-repo-test.git
cd git-filter-repo-test/

Executei novamente o comando:

git filter-repo --path python-logo.png --invert-paths

Parsed 16 commits
New history written in 0.08 seconds; now repacking/cleaning...
Repacking your repo and cleaning out old unneeded objects
HEAD is now at f025700 detalhe em um comando
Enumerating objects: 50, done.
Counting objects: 100% (50/50), done.
Delta compression using up to 8 threads
Compressing objects: 100% (27/27), done.
Writing objects: 100% (50/50), done.
Total 50 (delta 23), reused 32 (delta 21), pack-reused 0
Completely finished after 0.15 seconds.

Desta vez parece bom!

O arquivo python-logo.png sumiu do diretório corrente.

Porém, o repositório on-line, no github, ainda tem o arquivo de imagem.

Tentando dar um simples push nesse meu fresh clone, que foi limpo, para o meu repositório on-line, descobri que não e possível. A ligação com o repositório on-line foi perdida.

Para corrigir isso preciso adicionar o repositório remoto ao local.

git remote add origin https://github.com/anselmobd/git-filter-repo-test.git

Depois disso ainda tenho que forçar um push all.

git push origin --force --all

Agora sim!

Verificando o repositório no github, o arquivo python-logo.png sumiu de lá também e o número de commits lá diminuiu de 1, exatamente que foi o commit que inseriu a imagem lá.

Atualizando agora o repositório em produção

No diretório original, onde o sistema ficou rodando tive que fazer um rebase para ficar compatível com o repositório online.

git pull --rebase

Feito o rebase, o arquivo python-logo.png sumiu do diretório do repositório de produção.

Testando o funcionamento da aplicação, apareceu:

    Oi, mundo!

Show! Tudo certo!

Lembrando que a limpeza não foi feita no repositório do desenvolvimento, o procedimento de rebase deve ser feito lá também.

Agora, sim, depois dos testes, posso partir para limpar meu repositório indevidamente inchado.

Nenhum comentário:

Postar um comentário