Exemplo De Um Conflito - 14 Tipos De Conflitos E Suas Solues Com Exemplos
14 Tipos De Conflitos E Suas Solues Com Exemplos

Quando o merge dá errado na vida real

Eu estava trabalhando num branch de refatoração de uma API Python há dois anos quando o git travou em cima de mim. Três commits do meu colega que tocavam a mesma função de validação de email, mais o meu commit com uma correção de segurança que eu achei que era isolada. O resultado foi um conflito que tinha 47 linhas de marcador — não dois, não dez, oitoenta e tanta linhas empilhadas uma sobre a outra sem significado óbvio. O que eu preciso entender no final é simples: você quer saber como resolver um exemplo de conflito desses, não o que é teoria de versionamento. Vou direto.

Como funciona um exemplo de conflito no dia a dia

Você tem dois ramos que mudaram o mesmo arquivo. O Git não consegue adivinhar qual mudança você quer manter, então ele para tudo e coloca marcadores. Parece isso: <<<<<<< HEAD
def validar_email(usuario):
    return re.match(r".+@.+\..+", usuario)
=========
def validar_email(usuario):
    try:
        validate_email(usuario)
    except InvalidEmail:
        raise ValueError("email inválido")
>>>>>>> branch-remoto

O Git separou com essas linhas horizontais. Acima delas está o que estava no branch atual (HEAD). Abaixo está o que veio do outro branch. Entre os marcadores estão as duas versões colidindo. A maior parte das pessoas resolve isso abreviando: aperta merge, vê os conflitos, abre o arquivo, escolhe uma versão e salva. Isso funciona para arquivos pequenos. Não funciona quando o conflito envolve lógica condicional ou chamadas de API.

No meu caso, a função que meu colega tinha refatorado usava uma biblioteca nova (pydantic) para validação, enquanto minha correção de segurança apenas adicionava uma validação de caracteres especiais. O conflito não era entre "o que ele fez" versus "o que eu fiz". Era entre duas abordagens diferentes que ambas precisavam sobreviver. A solução que eu encontrei foi ler cada lado do conflito individualmente, identificar que minha correção era um patch sobre a função do colega, e então reconstruir a função final incluindo a lógica de pydantic E a validação de caracteres. Eu não mergei automaticamente. Eu reescrevi do zero naquela seção, porque o merge automático teria perdido a correção de segurança em algum ponto.

Erros comuns que todo mundo comete

O primeiro erro é aceitar a resolução automática sem ler o arquivo inteiro depois. O git mergetool pode resolver o conflito visualmente, mas ele não entende o contexto do seu domínio. Se você está lidando com código financeiro, transações concorrentes, ou qualquer coisa que tenha estado compartilhado, a resolução automática provavelmente vai introduzir um bug silencioso. O segundo erro é ter preguiça de testar após resolver. Um conflito resolvido é um arquivo que existe em duas versões que nunca foram testadas juntas. Pelo menos rode os testes unitários relevantes. Se não existirem testes relevantes, talvez você deva estar preocupado com outra coisa além do merge.

👉 Clique no botão abaixo para saber mais sobre o assunto!

O terceiro erro, e esse é mais sutil, é não registrar porquê você escolheu uma versão em vez da outra. Comentar o motivo na mensagem de commit ou num arquivo de changelog evita que alguém no futuro pergunte "por que essa validação foi removida" e você não consiga explicar.

Quando o Git não ajuda

A principal limitação do sistema de conflitos do Git é que ele opera no nível de texto plano. Ele não entende a estrutura do seu código. Se dois desenvolvedores reorganizarem as mesmas dez linhas de importação de formas diferentes, o Git vai mostrar um conflito enorme mesmo quando semanticamente não haveria problema nenhum. Isso é especialmente problemático em projetos grandes onde os desenvolvedores não têm padronização de formatação. O Black ou o Prettier podem reduzir essa fricção em até 60 por cento dos conflitos, mas eles não eliminam conflitos de lógica.

Existe outra limitação que ninguém menciona: conflitos em arquivos binários. Uma imagem, um arquivo decompiled, um pickle de dados. O Git simplesmente não consegue fazer diff nesses casos. A resolução é sempremanual — você escolhe uma versão ou a outra, ou recria o arquivo do zero. Não há ferramenta mágica para isso.

Um workaround que eu uso atualmente

Quando vejo que um merge vai gerar muitos conflitos, eu não deixo o Git resolver tudo de uma vez. Eu divido o processo em etapas menores. Primeiro, faço um merge parcial se possível. Depois resolvo os conflitos um arquivo por vez, testando após cada resolução. Se um arquivo tiver mais de vinte linhas de conflito, eu paro e leio com calma antes de prosseguir. Também começou a valer a pena para mim documentar os tipos de conflito que aparecem com frequência no meu projeto. Tenho um arquivo README_CONFLICTS.md no repositório que lista os três padrões mais comuns e como resolvê-los. Reduz o tempo médio de resolução de conflitos repetidos de trinta minutos para cinco.

Se você está começando agora, não tente aprender resolvendo conflitos complexos. Comece com branches que têm mudanças óbvias e não sobrepostas. Entenda o que o Git está te dizendo antes de tentar manipular os marcadores manualmente. A maioria dos conflitos é mais simples do que parece na primeira olhada.