Mesclar duas bases de código: escolha uma fonte da verdade e migre com segurança
Mescle duas bases de código sem duplicar bugs escolhendo uma fonte da verdade clara, migrando funcionalidades passo a passo e validando autenticação, dados e segurança.

Por que duas bases de código geradas por AI viram um problema rápido
Duas ferramentas de AI podem produzir duas versões bem diferentes do mesmo app em um fim de semana. Talvez você tenha começado com um v0 para ganhar velocidade, depois refeito em Replit quando as coisas ficaram bagunçadas. Ou um colega tentou Lovable ou Bolt e “consertou” algumas telas lá. Cada repositório pode parecer convincente por si só, então é tentador manter os dois e resolver depois.
É aí que começa a dor. Protótipos divergem rápido. A interface pode parecer igual, mas a lógica por baixo normalmente não é. Um repositório armazena papéis em uma tabela; o outro guarda em um JSON blob. Um assume login por email, o outro assume OAuth. Uma semana depois você não tem apenas duas bases de código. Você tem dois conjuntos de suposições.
Falhas comuns aparecem rápido:
- O mesmo bug existe duas vezes, mas com sintomas diferentes.
- Regras de negócio entram em conflito (preços, permissões, estados), então o “correto” depende de qual repositório você executa.
- Modelos de dados divergem, tornando migrações arriscadas e relatórios pouco confiáveis.
- Correções de segurança aparecem em apenas um lugar, deixando o outro como uma armadilha.
Tentar mesclar duas bases de código linha a linha geralmente piora as coisas. Você acaba costurando padrões incompatíveis, copiando fluxos de autenticação quebrados e puxando queries inseguras ou segredos vazados do repositório mais fraco. O resultado é uma terceira base de código mais difícil de entender do que qualquer uma das originais.
Um bom resultado é simples: uma única fonte de verdade, um caminho de deploy e um lugar para consertar bugs. Você ainda pode reaproveitar boas ideias do outro repositório, mas apenas migrando funcionalidades de forma intencional. O objetivo não é “combinar tudo”. É “escolher uma para confiar e mover só o que puder verificar”.
O que “fonte da verdade” significa (e o que não significa)
Uma fonte da verdade é o repositório onde novas mudanças têm permissão para cair. Se uma feature é lançada, ela sai de lá. Se um bug é corrigido, a correção vai lá. Todo o resto vira material de referência, não um segundo produto em produção.
Isso não quer dizer que o repositório escolhido seja perfeito, limpo ou até mesmo o que você prefere. Também não significa apagar o outro repositório no dia um. Você pode mantê-lo para comparação ou para entender expectativas dos usuários. A diferença é governança: apenas um repositório avança.
Antes de escolher, defina o que “verdade” cobre para evitar discussões depois. Seja direto:
- Comportamento do produto (features e fluxos-chave de UX)
- Modelo de dados e migrações
- Autenticação e permissões
- Configuração de deploy e ambiente
- Logging e tratamento de erros
Então estabeleça uma regra que todos sigam: o repositório vencedor é o único caminho gravável. O outro vira somente leitura e permanece assim.
Defina também um prazo para decisão. Protótipos gerados por AI divergem rápido, especialmente quando duas ferramentas continuam gerando novos arquivos. Uma meta prática é 24 a 72 horas: escolha um, congele o outro e migre intencionalmente. Se não tiver certeza de qual repositório é mais seguro, uma auditoria rápida pode revelar problemas de alto risco cedo, especialmente em torno de autenticação, segredos e gravações no banco de dados.
Uma maneira rápida de comparar duas bases de código sem especialização profunda
Quando precisar mesclar duas bases, não comece debatendo qual “parece mais bonito”. Comece verificando qual delas se comporta como software real sob pressão básica: rodar, buildar, deployar e falhar de forma previsível.
Uma ficha de avaliação simples força uma comparação justa. Dê a cada repositório uma nota de 0-2 (0 = falha, 1 = instável, 2 = sólido) para:
- Roda localmente a partir de uma instalação limpa (sem passos manuais secretos)
- Constrói e deploya de maneira repetível
- Tem pelo menos alguns testes significativos (ou você pode adicioná-los rapidamente)
- Evita gambiarras (URLs hard-coded, config copiada, soluções temporárias aleatórias)
- Produz erros claros que você consegue agir sobre (não falhas silenciosas)
Em seguida, escaneie por sinais de alerta que você consegue identificar sem ser especialista em segurança: segredos commitados no repositório, bypasses de autenticação “temporários”, SQL bruto construído a partir de input do usuário ou rotas de API sem checagem de acesso. Se um repositório tem autenticação obviamente quebrada ou riscos claros de injeção, assuma que é um problema mais profundo do que parece.
Depois olhe a estrutura e higiene de build. Um repositório mais saudável costuma ter um layout óbvio (UI, backend, migrations), variáveis de ambiente em um só lugar e uma forma clara de rodar e deployar. Se a lógica está duplicada em arquivos aleatórios, nomes inconsistentes ou múltiplos arquivos de configuração competindo, você vai pagar por isso depois.
Por fim, faça um teste rápido de manutenibilidade: uma pessoa nova consegue achar onde o login acontece, onde os dados são armazenados e onde ficam as rotas principais da API em 30 minutos? Se não, bugs vão voltar depois de “correções”.
Passo a passo: escolha o repositório vencedor e congele o outro
Manter dois repositórios ativos dobra seus bugs e decisões. O caminho mais rápido é escolher um como fonte da verdade e tratar o outro apenas como doador de features.
Escolha a base que seja mais segura e mais fácil de entregar, mesmo que a UI pareça menos polida. Segurança significa menos desconhecidos, menos atalhos e menos lugares onde uma mudança quebra três telas.
Se estiver em dúvida, avalie ambos com algumas checagens práticas:
- Alguém novo consegue rodar localmente sem trabalho de detetive?
- A autenticação funciona de ponta a ponta (cadastro, login, reset, logout)?
- Os segredos são tratados com segurança (não hard-coded ou expostos)?
- O modelo de dados é consistente (um esquema claro, hacks mínimos)?
- Você consegue deployar sem correções manuais pontuais?
Uma vez escolhido o vencedor, congele o outro repositório. Sem novas features, sem “consertos rápidos”, sem reconstrução paralela. Deixe-o somente leitura para que não haja deriva silenciosa que puxe a equipe de volta ao desenvolvimento dividido.
Em seguida, escreva uma lista curta do que deve ser mantido do repositório perdedor. Descreva resultados, não telas: “usuários podem exportar faturas”, “admins podem reembolsar”, “clientes podem atualizar método de pagamento”. Isso vira seu backlog de migração.
Finalmente, documente os não negociáveis em um só lugar: usuários, pagamentos, permissões e os fluxos centrais que mantêm o negócio vivo. Exemplos:
- Usuários existentes devem fazer login com o mesmo email.
- Não cobrar em duplicidade.
- Apenas admins podem ver dados de clientes.
Passo a passo: migrar features sem copiar bugs
A abordagem mais segura é chata: mover um fluxo de usuário funcionando por vez e provar que funciona antes de tocar no próximo.
Comece com a menor fatia vertical que você consegue entregar de ponta a ponta. Escolha um fluxo que envolva UI, backend e dados, mas que permaneça contido (por exemplo: cadastro, criar um item e vê-lo na lista). Isso revela rapidamente roteamento, formato de API e suposições de banco sem te prender em casos de borda sem fim.
Porte comportamento, não código
Trate o repositório antigo como uma especificação, não como um arquivo fonte a copiar. Leia o que ele faz e reimplemente esse comportamento de forma limpa no repositório novo. Copiar arquivos é como importar globals escondidos, consultas inseguras e gambiarras do tipo “funciona na minha máquina”.
Um loop prático:
- Escreva entradas esperadas, saídas e mensagens de falha para o fluxo.
- Reconstrua os endpoints e a UI com base nesse comportamento.
- Mantenha mudanças no modelo de dados ao mínimo até o fluxo estar estável.
- Adicione uma pequena feature flag (até um toggle de configuração) para ligar/desligar o fluxo novo.
Uma vez que a fatia funcione, mova a próxima feature do mesmo jeito. Mantenha migrações pequenas e PRs focados. Migrar duas features não relacionadas ao mesmo tempo dificulta saber o que quebrou.
Verifique após cada movimento
Depois de cada feature, rode as mesmas checagens rápidas:
- Complete o fluxo duas vezes (usuário novo e usuário existente).
- Verifique que os dados no banco batem com o esperado.
- Confirme que não surgiram novos erros ou avisos nos logs do servidor.
- Confirme que é possível reverter (desligar o toggle).
Se um repositório tem convites de equipe, não copie o código de convite fielmente. Recrie o comportamento do convite (quem pode convidar, o que é enviado, como aceitação funciona) e confirme que não há vazamento de tokens nos logs.
Áreas de alto risco: autenticação e migrações de dados
Ao mesclar duas bases, as partes mais propensas a quebrar em produção são autenticação e dados. Elas costumam parecer “prontas” em uma demo, mas pequenas diferenças entre repositórios podem bloquear usuários, vazar dados ou corromper registros.
Autenticação: prove de ponta a ponta
Audite autenticação antes de mover features que não são essenciais. Não basta checar que existe uma página de login. Verifique o ciclo completo: sign-in, armazenamento de sessão, logout e como os erros se comportam.
Suas checagens básicas de auth devem cobrir:
- Login funciona com contas reais, não apenas usuários demo.
- Sessões persistem após refresh e expiram quando devem.
- Tokens de reset de senha funcionam e não podem ser reutilizados.
- Callbacks OAuth correspondem aos domínios e caminhos de redirecionamento corretos.
- Papéis e permissões correspondem ao que você realmente pretende (admin vs membro vs convidado).
Uma falha comum durante migração: Repo A usa sessões via cookie e Repo B usa tokens no localStorage. Ambos podem “funcionar” sozinhos, mas misturá-los gera logouts aleatórios e proteções quebradas.
Migrações de dados: mapeie o modelo e mova com segurança
Antes de migrar features, descreva o modelo de dados em linguagem simples: tabelas ou coleções, campos obrigatórios, relacionamentos e o que pode ser nulo. Se o mesmo conceito tem nomes diferentes (userId vs owner_id), trate como problema de migração, não como search-and-replace.
Planeje migrações como um release controlado:
- Faça um backup que você consiga restaurar rapidamente.
- Ensaie em staging com volume de dados realista.
- Defina rollback (e o que significa se dados parciais já tiverem sido movidos).
- Migre em pequenos lotes sempre que possível.
- Valide totais e verifique registros críticos (usuários, pagamentos, permissões).
Verificação em prazo apertado: testes que você realmente precisa
Velocidade importa, mas pular checagens básicas é como enviar o mesmo bug duas vezes. O objetivo não é cobertura perfeita. É confiança de que a nova fonte da verdade funciona para usuários reais.
Comece travando um conjunto mínimo de checagens end-to-end. São os fluxos que provam que o app é utilizável e financeiramente seguro:
- Cadastro e onboarding (como for seu processo real)
- Login, logout e reset de senha
- O fluxo central pelo qual os usuários pagam
- Pagamentos e reembolsos (se houver), incluindo um pagamento falho
- Uma ação de admin ou configuração que altera dados
Depois acrescente algumas checagens automáticas baratas que detectam quebras cedo:
- Linting e formatação
- Checagem de tipos (se usar TypeScript)
- Um número pequeno de testes unitários onde a lógica é estável
Mantenha staging próximo da produção. Use os mesmos nomes e método de carregamento de variáveis de ambiente e o mesmo tipo de banco. Uma falha clássica é “funciona em staging” porque staging usa SQLite enquanto produção usa Postgres.
Enquanto verifica, mantenha um diário curto de bugs: o que quebrou, onde foi consertado e o que teria pegado antes (um teste, uma regra de linter, uma variável de ambiente faltante). Isso evita que o mesmo bug volte em migrações futuras.
Armadilhas comuns que recriam a mesma bagunça
A maioria das equipes se complica quando trata a mesclagem como um exercício de “melhor dos dois”. Se ambos os repositórios foram produzidos rapidamente por diferentes ferramentas de AI, eles frequentemente compartilham os mesmos pontos fracos, só em lugares diferentes.
Essas armadilhas tendem a recriar a bagunça:
- Fazer uma única grande fusão e passar semanas desenrolando conflitos e lógica duplicada.
- Copiar e colar arquivos inteiros para mover features e importar padrões inseguros (segredos hard-coded, SQL inseguro, checagens de auth faltando).
- Mudar UI e backend ao mesmo tempo, assim você não sabe qual mudança quebrou algo.
- Deixar dependências divergirem e então builds falharem em uma máquina limpa ou no CI.
- Tratar deploy como etapa final e descobrir tarde que variáveis de ambiente, migrações ou pressupostos de hospedagem não batem com a realidade.
Um exemplo pequeno: você copia uma página de login “funcional” do Repo B para o Repo A. Ela parece ok, mas traz também um helper que loga tokens no console e pula checagens de sessão no servidor. Você consertou a tela, mas reintroduziu a brecha de segurança.
Guardrails que mantêm o progresso:
- Mova uma fatia de feature por vez e adicione um checkpoint antes da próxima.
- Reimplemente o comportamento mínimo no repositório vencedor em vez de copiar arquivos.
- Trave versões de runtime e pacotes cedo e então verifique instalações limpas.
- Faça um dry run de deploy assim que a primeira feature migrada cair.
Checklist rápido antes de se comprometer com a troca
Antes de mesclar duas bases em um único caminho, pare e confirme que dá para viver com a decisão nas próximas semanas. O objetivo é entregas previsíveis e menos surpresas.
Primeiro, deixe o repositório perdedor seguro para ser mantido sem que ele continue mudando. Se pessoas ainda puderem empurrar correções rápidas lá, você vai acabar com duas realidades de novo.
Use isso como um portão:
- O repositório antigo está congelado (somente leitura), claramente marcado como arquivado, e você registrou o último commit ou tag conhecido como bom.
- O repositório escolhido builda do zero em uma máquina limpa usando passos escritos (install, env vars, build, run), e esses passos funcionam duas vezes seguidas.
- O deploy é repetível e você consegue reverter para o build anterior.
- Login e cadastro funcionam de ponta a ponta para usuários novos e existentes, incluindo resets e expiração de sessão.
- Não há segredos commitados e as variáveis de ambiente estão documentadas.
Uma forma concreta de validar o último item: rode as três jornadas principais do usuário em staging (por exemplo: cadastro, completar a tarefa principal, pagar ou exportar), usando contas de teste e volume de dados similar à produção.
Exemplo: escolher entre um build v0 e um rebuild no Replit
Um fundador acaba com duas versões do mesmo app. A primeira é um build v0 que parece ótimo e tem a maioria das telas, mas é majoritariamente frontend. A segunda é uma reconstrução full-stack no Replit que consegue fazer login e salvar dados, mas a UI é áspera e partes da lógica estão duplicadas.
O objetivo não é mesclar linha a linha. É escolher um repositório como fonte da verdade e mover só as partes que merecem ficar.
Eles comparam os dois repositórios usando algumas checagens:
- Qual tem autenticação funcionando de ponta a ponta (cadastro, login, logout, expiração de sessão)?
- Qual tem um modelo de dados mais limpo (nomes mais claros, menos campos pontuais)?
- Qual faz deploy sem passos manuais ou chaves espalhadas no repositório?
- Qual tem menos “fixes mágicos” (IDs hard-coded, rotas admin escondidas, timeouts aleatórios)?
Nesse caso, o Replit vence porque a autenticação funciona e o modelo de dados está mais próximo do que o negócio precisa. O v0 vira apenas referência de design.
A migração acontece feature por feature. Em vez de copiar toda a UI do v0, a equipe reconstrói as telas-chave como componentes dentro do repositório Replit, ligados ao backend existente. Eles começam pelos fluxos de maior valor: onboarding, painel principal e a ação que o usuário faz todo dia.
Antes de chamar pronto, eles validam comportamento, não só aparência. Papéis e permissões precisam bater, formulários precisam ter os mesmos campos obrigatórios e estados de erro devem ser claros (senha errada, campo obrigatório, gravação falhou).
Próximos passos: chegar a uma base de código pronta para envio
Se você precisa mesclar duas bases, a forma mais rápida de parar o caos é pausar trabalho de features e fazer uma auditoria escrita curta. Você não está julgando estilo de código. Está identificando o que é seguro para produção e o que vai quebrar depois.
Anote o que você sabe hoje:
- Os bugs de maior dor para o usuário (o que, onde, como reproduzir)
- Os maiores riscos (segurança, perda de dados, custos surpresa)
- As features que precisa manter (e o que pode esperar)
- O que já funciona em produção (mesmo que seja feio)
- O que bloqueia deploy (env vars, passos de build, migrações faltando)
Então tome uma decisão: consertar e migrar, ou reconstruir do zero usando os mesmos requisitos. Se um repositório tem modelo de dados estável e deploy previsível, ele costuma vencer mesmo que a UI fique atrasada. Se ambos estão instáveis, uma reconstrução limpa pode sair mais barato do que arrastar dois conjuntos de problemas.
Traga ajuda assim que vir sinais de alerta como segredos expostos, autenticação inconsistente, propriedade do banco de dados pouco clara ou deploys que só funcionam em uma máquina.
Se você herdou protótipos gerados por AI e quer uma base pronta para produção, FixMyMess (fixmymess.ai) foi feito exatamente para essa situação. Eles podem diagnosticar ambos os repositórios, reparar lógica quebrada, endurecer a segurança, refatorar arquitetura confusa e preparar o app para deploy. Se não souber qual repositório deve vencer, começar pela auditoria de código gratuita pode dar um plano claro e de baixo impacto antes de você se comprometer.
Perguntas Frequentes
Devo mesclar os dois repositórios ou escolher um e migrar?
A maioria das equipes deve escolher um repositório como fonte da verdade e migrar as funcionalidades de forma intencional. Manter os dois repositórios “ativos” costuma dobrar bugs, brechas de segurança e decisões, e a situação piora a cada semana.
Como escolho a base vencedora se não sou técnico?
Escolha o repositório que seja mais seguro e mais fácil de colocar em produção, não o que parece mais bonito. Prefira o que roda a partir de uma instalação limpa, que deploya de forma repetível, que tem autenticação funcionando de ponta a ponta e que possui menos gambiarras como URLs hard-coded ou bypasses escondidos.
O que significa “congelar” o repositório perdedor?
Torne-o somente leitura e defina uma regra clara de que todo novo trabalho acontece apenas no repositório escolhido. Mantenha o repositório perdedor como referência, mas pare de fazer deploy a partir dele para que ele não volte a ser uma segunda versão ativa.
Qual é uma maneira rápida de comparar duas bases de código geradas por AI?
Comece com as mesmas checagens básicas em ambos: instalação limpa, execução local, build, deploy e erros previsíveis. Em seguida, procure sinais óbvios como segredos commitados, bypasses de autenticação, escritas de banco de dados inseguras ou rotas de API sem checagem de acesso.
Por que mesclar linha a linha costuma ser uma má ideia?
Porque eles frequentemente discordam em suposições centrais como modelos de dados, sessões de autenticação e regras de negócio. O resultado costuma ser uma terceira base que herda o pior dos dois e é mais difícil de depurar do que qualquer uma das originais.
Como migrar funcionalidades sem copiar bugs?
Portar o comportamento, não os arquivos. Trate o repositório antigo como uma especificação: escreva entradas, saídas e estados de erro esperados, e reimplemente esse comportamento de forma limpa no repositório fonte da verdade para não importar globals escondidos, consultas inseguras ou atalhos “funciona na minha máquina”.
Qual é o plano de migração mais rápido e seguro em prazo apertado?
Comece com um pequeno fluxo vertical que envolva UI, backend e dados, como cadastro e criação de um registro. Após cada migração, execute o fluxo duas vezes, verifique os dados escritos no banco e confirme que os logs não mostram novos erros para detectar deriva cedo.
Quais são as partes de maior risco ao combinar duas versões do mesmo app?
Autenticação e migrações de dados. Se sessões, papéis, resets ou permissões estiverem errados, usuários podem ser bloqueados ou ver dados incorretos. Migrações descuidadas podem corromper registros ou quebrar relatórios.
Qual o teste mínimo necessário antes de trocar para um repositório único?
Execute um conjunto pequeno de verificações end-to-end para os fluxos que mantêm o negócio vivo, especialmente login/logout/reset e o principal fluxo que os usuários pagam para usar. Acrescente automação leve como linting e checagens de tipos para evitar regressões óbvias durante migrações.
Quando devo trazer ajuda externa e o que a FixMyMess pode fazer?
Chame ajuda externa quando notar segredos expostos, autenticação quebrada ou inconsistente, propriedade do banco de dados pouco clara ou deploys que só funcionam em uma máquina. FixMyMess se especializa em diagnosticar bases geradas por AI, escolher uma fonte de verdade segura e deixar o app pronto para produção rapidamente, muitas vezes começando por uma auditoria de código gratuita para mapear riscos antes de tomar uma decisão.