Ir para o conteúdo

Domando a Complexidade do Projeto - A Saga

Versionando o Ambiente de Desenvolvimento Sem Poluir Seu Repositório Principal

À medida que os projetos evoluem, especialmente bases de conhecimento ou sites de documentação que envolvem múltiplas ferramentas como MkDocs, Obsidian, scripts personalizados e IDEs especializadas como Cursor, a complexidade aumenta naturalmente. A integração dessas ferramentas cria fluxos de trabalho poderosos, mas também introduz um novo desafio: gerenciar o número crescente de arquivos de configuração, rascunhos, scripts e documentos de planejamento que suportam o projeto principal.

O Ponto Crítico: Quando .gitignore Não é Suficiente

Recentemente, atingi um marco doloroso que muitos desenvolvedores encontram: perder várias horas de trabalho. O culpado? Arquivos cruciais para o meu fluxo de trabalho de desenvolvimento não estavam sob controle de versão.

Como muitos, eu queria manter meu repositório GitHub voltado para o público limpo. Para este projeto, isso significava confirmar apenas o conteúdo principal em Markdown e os arquivos essenciais do MkDocs necessários para construir o site. Todo o resto – minha configuração do cofre do Obsidian, configurações do Cursor, scripts de tradução em rascunho, notas de planejamento de tarefas – estava diligentemente listado em .gitignore. Isso manteve o repositório principal organizado, mas deixou meu andaime de desenvolvimento vital desprotegido.

Este chamado de atenção aconteceu relativamente cedo, felizmente. Enquanto trabalhava na integração de ferramentas de tradução e no planejamento do fluxo de trabalho usando notas dentro da estrutura do meu projeto, um incidente sobrescreveu um trabalho de planejamento significativo. Frustrante, sim, mas uma lição valiosa aprendida antes que os riscos aumentassem.

Procurando uma Solução: As Tentativas Fracassadas

Minhas ideias iniciais giravam em torno de usar o próprio Git de forma mais inteligente, mas encontrei obstáculos.

Tentativa 1: Repositórios Aninhados - O Pesadelo da Troca de Branches

Meu primeiro pensamento foi explorar maneiras de ter múltiplos históricos Git dentro do mesmo diretório de projeto, talvez usando repositórios aninhados. A ideia era ter um repositório "dev" de nível superior rastreando tudo (configurações de IDE, rascunhos, arquivos do repositório interno) enquanto o repositório "público" interno continha apenas os arquivos limpos e implantáveis do projeto. O repositório externo ignoraria o diretório .git do repositório interno.

Em teoria, isso parecia uma abordagem em camadas elegante. No entanto, quando realmente tentei configurar isso, percebi muito rapidamente que não estava funcionando. Em primeiro lugar, o Git não suporta realmente repositórios aninhados, pelo menos não da maneira que eu imaginava. E faz sentido. Há uma ressalva que eu não tinha pensado: digamos que estou trabalhando no repositório interno (docs-nica) e mudo para um branch diferente. Agora, todos os arquivos nessa pasta mudam (para refletir o branch) – mas o repositório externo (docs-nica-dev) ainda está em seu branch principal. O repositório externo agora vê todas essas alterações de arquivo e pensa que são alterações em seu branch principal... É claramente visível por que isso é um problema. Ok, então essa abordagem não estava funcionando.

Tentativa 2: Repositórios Separados + Hooks Git - A Catástrofe da Cópia

De volta à prancheta. Minha próxima ideia foi ter dois repositórios completamente separados. Um dev que contém tudo o que preciso (scripts, notas, configurações, e os arquivos principais do projeto). E um public que contém apenas o conteúdo Markdown e a configuração do MkDocs – apenas o essencial, da maneira que se destina à implantação.

Mas aqui vem o problema: se mudarmos algo no repositório public (talvez uma correção rápida diretamente lá, ou puxando as alterações dos colaboradores), como o repositório dev saberá disso? E mais comumente, como as alterações em dev são refletidas em public? Precisamos de alguma forma de vinculá-los.

A primeira ideia foi usar hooks do GitHub (ou hooks Git locais). Eles permitem definir comandos para serem executados após certas ações do Git, como um commit. Configurei um hook que, após um commit no repositório dev, basicamente apenas copiaria os arquivos relevantes (a pasta docs/, mkdocs.yml, etc.) para o diretório do repositório public.

Pareceu funcionar à primeira vista, mas essa abordagem teve dois problemas principais:

  1. Histórico Barulhento: O hook copiou todos os arquivos relevantes em cada commit. Isso significou que o repositório public sempre pensou que todo o seu conteúdo havia mudado. Embora tecnicamente não quebrasse nada, o histórico de commits tornou-se menos útil, mostrando centenas (ou milhares) de arquivos alterados em cada commit, tornando impossível identificar instantaneamente quais conteúdos de arquivo realmente mudaram.
  2. Cegueira à Exclusão: O script apenas copiava arquivos. Se eu excluísse um arquivo ou pasta no repositório dev, essa alteração não seria refletida no repositório public. O arquivo antigo simplesmente permaneceria lá.

Droga, já gastei horas nisso – e ainda nenhuma solução funcionando.

O Avanço: Repositórios Separados + Sincronização de Arquivos

Então me lembrei de um software de código aberto que eu havia testado há muito tempo para sincronizar pastas locais: FreeFileSync. Embora seja lamentável adicionar outro conjunto de ferramentas/software à pilha necessária, ele realmente realizou exatamente o que eu queria.

A configuração agora envolve:

  1. Dois repositórios Git separados: docs-nica-dev (contendo tudo) e docs-nica (a versão pública limpa).
  2. FreeFileSync: Usado para definir as regras de como sincronizar as pastas específicas (como docs/, arquivos de tema, mkdocs.yml) entre os dois locais de repositório. Ele pode lidar com sincronizações bidirecionais, espelhamento e, crucialmente, propagar exclusões corretamente.
  3. RealTimeSync (parte do FreeFileSync): Usado para monitorar as pastas definidas em busca de alterações e acionar a sincronização automaticamente com base nas regras do FreeFileSync.

Essa combinação finalmente preenche a lacuna entre os dois repositórios de forma eficaz. As alterações feitas nas pastas de conteúdo principal do repositório dev são espelhadas para o repositório public, e vice-versa, se necessário (embora meu fluxo principal seja dev -> public). As exclusões são tratadas corretamente e, como ele sincroniza apenas os arquivos alterados, o histórico de commits no repositório public reflete com precisão as modificações reais.

A Ressalva Restante: Sincronização vs. Momento do Commit

Ainda há uma desvantagem, no entanto. Quando altero um arquivo no repositório dev, e o RealTimeSync está em execução, essas alterações são sincronizadas para o diretório do repositório public imediatamente, mesmo que ainda não tenham sido confirmadas no repositório dev. A solução de sincronização é desacoplada do Git.

Não é um grande problema, mas requer um pouco mais de cuidado ao confirmar e enviar alterações. Basicamente, quando trabalho no repositório dev, preciso garantir que confirmo tudo lá antes de mudar o foco para o repositório public para confirmar e enviar. Além disso, reforça o hábito de realmente revisar as alterações preparadas para commit no repositório public antes de realmente confirmar e enviar, apenas para garantir que o estado seja exatamente o que pretendo.

Para Quem é Isso? (Esclarecimento Importante)

Espere um pouco, antes que você pense que toda essa configuração é obrigatória apenas para usar o wiki, deixe-me esclarecer. Toda essa complexidade? Ela não é necessária se você quiser apenas trabalhar com o conteúdo principal. O ponto de entrada principal ainda é super simples: clone o repositório público docs-nica (que tem apenas os arquivos Markdown e a configuração do MkDocs) e use as ferramentas que você preferir. É isso.

Então, por que eu passei por todo esse problema? Essa configuração de desenvolvimento bastante complexa serve a dois propósitos principais para mim:

  1. Meu Rede de Segurança Pessoal: É um controle de versão crucial para todas as minhas peças e pedaços de desenvolvimento – as configurações, os scripts inacabados, as notas de planejamento – coisas que não posso me dar ao luxo de perder novamente.
  2. Compartilhando Meu Fluxo de Trabalho Exato (Opcionalmente): Se alguém quiser replicar meu ambiente específico, ele pode clonar o repositório docs-nica-dev. Eles obterão minha configuração completa do Obsidian (plugins, configurações, favoritos, pesquisas, tudo!), potencialmente configurações do Cursor e quaisquer outras ferramentas integradas que eu tenha configurado. É uma maneira de compartilhar uma configuração base pronta para uso.

Mas a ideia fundamental não mudou: você pode absolutamente pegar apenas o repositório público e construir seu próprio fluxo de trabalho em torno dele com suas ferramentas favoritas. Essa dança elaborada é sobre gerenciar meu caos de desenvolvimento e oferecer um modelo para aqueles que o desejam.

Conclusão: Uma Solução Conquistada a Duras Penas

No geral, estou feliz por ter encontrado uma solução para o problema agora – mesmo que isso me tenha custado cerca de dois dias de tentativa, erro e frustração. Mas acertar esse fluxo de trabalho foi crucial para evitar problemas futuros, garantindo tanto um repositório público limpo quanto um ambiente de desenvolvimento totalmente controlado por versão.

Essa configuração é perfeita? Requer o gerenciamento de dois repositórios e uma ferramenta de sincronização externa, além de um fluxo de trabalho consciente para commits. No entanto, resolve diretamente o problema crítico de versionar tudo o que é necessário para um processo de desenvolvimento complexo, sem comprometer a limpeza do repositório principal ou lutar contra as limitações do Git com estruturas aninhadas. Para projetos que superam estratégias simples de .gitignore, essa abordagem oferece um caminho pragmático, proporcionando segurança e estrutura para a realidade inevitável e confusa do trabalho de desenvolvimento.