Mesclar ou fundir — é a ação de combinar dois branches no Git, unindo alterações de um branch para outro. No desenvolvimento moderno, o merge é a forma padrão de integrar um branch de funcionalidade ao branch principal do projeto. De acordo com o GitHub Octoverse 2024, mais de 15 milhões de merges são realizados diariamente. Merge é um mecanismo chave do trabalho colaborativo, permitindo combinar o esforço de vários desenvolvedores em um único produto.
Principais Pontos
Merge no Git é a operação de combinar dois ou mais históricos de desenvolvimento em um. Quando um desenvolvedor mescla um branch, o Git encontra automaticamente o ancestral comum (base commit) e cria um novo commit de merge que inclui alterações de ambos os branches. Three-way merge é o algoritmo padrão que compara três estados: o ancestral comum, o primeiro branch e o segundo branch.
O processo de merge começa com o comando git merge. O Git determina o ponto de divergência dos branches e aplica sequencialmente as alterações do branch de origem sobre o branch de destino. Se as alterações não entrarem em conflito, o Git realiza um fast-forward ou cria um merge commit dependendo das configurações. Fast-forward é um cenário onde o branch de destino simplesmente avança para os commits do branch de origem.
# Mudar para o branch de destino e mesclar
git checkout main
git merge feature/payment-module
# Mesclar com no-fast-forward explícito
git merge --no-ff feature/payment-module
# Abortar merge se os conflitos forem muito complexos
git merge --abort
A flag --no-ff (no fast-forward) força a criação de um merge commit mesmo quando um fast-forward é possível. Isso preserva a informação de que as alterações foram feitas em um branch separado. Muitas equipes preferem esta abordagem para manter o histórico de ramificação de forma explícita.
O Git tem três estratégias principais de fusão de branches, cada uma adequada para um cenário específico. A escolha da estratégia depende da cultura da equipe e dos requisitos de limpeza do histórico do projeto.
| Estratégia | Resultado | Quando usar |
|---|---|---|
| Standard merge | merge commit + histórico completo | equipes que valorizam o histórico completo |
| Squash merge | um commit, histórico comprimido | branches de funcionalidade com muitos commits pequenos |
| Rebase merge | histórico linear, sem merge commit | branches de funcionalidade pessoais, antes de criar um PR |
Standard merge cria um merge commit com dois pais. O histórico completo é preservado, mas o grafo de ramificação se torna mais complexo. Squash merge combina todos os commits de um branch de funcionalidade em um e o aplica sobre o branch de destino — o histórico se torna linear e limpo, mas a informação sobre estágios intermediários é perdida.
Rebase, embora não seja um merge completo, atinge o mesmo resultado — as alterações de um branch são movidas para cima de outro. A diferença é que o histórico é reescrito: os commits do branch de funcionalidade são recriados sobre o último commit do branch de destino. Isso dá um histórico perfeitamente linear, mas requer force push ao enviar.
Um conflito de merge surge quando as mesmas linhas de um arquivo são alteradas em dois branches. O Git não pode determinar automaticamente qual versão manter e requer intervenção do desenvolvedor. Os conflitos são exibidos nos arquivos usando marcadores especiais: <<<<<<<, =======, >>>>>>>.
O processo de resolução de conflitos envolve várias etapas. Primeiro, o desenvolvedor abre o arquivo em conflito e seleciona manualmente as alterações necessárias. É importante não apenas escolher uma versão, mas entender a lógica de ambas as alterações e tomar uma decisão correta. Após editar o arquivo, os marcadores de conflito são removidos e as alterações são adicionadas à staging area via git add.
# Ver lista de arquivos em conflito
git status
# Iniciar mergetool (ex.: VS Code, IntelliJ)
git mergetool
# Depois de resolver todos os conflitos
git add .
git merge --continue
# Ou abortar o merge completamente
git merge --abort
Usar ferramentas visuais de merge acelera significativamente a resolução de conflitos. VS Code, IntelliJ IDEA e GitKraken fornecem interfaces com três painéis: branch atual, branch de entrada e resultado. A ferramenta git mergetool abre automaticamente o editor configurado para cada arquivo em conflito.
A melhor forma de evitar conflitos complexos é a sincronização regular do branch de funcionalidade com o branch principal. Se um desenvolvedor mescla main em seu branch uma vez por dia, os conflitos serão pequenos e facilmente resolvíveis. Acumular alterações por uma semana garante conflitos complexos com alto risco de erros.
Rebase e merge são duas formas de combinar alterações, e a escolha entre eles frequentemente gera debates nas equipes. Rebase move commits de um branch para cima de outro, reescrevendo o histórico. Merge cria um novo commit de merge, preservando o histórico de ramificação. Cada abordagem tem suas vantagens e limitações.
Rebase é apropriado quando um desenvolvedor está trabalhando em seu branch de funcionalidade local e quer um histórico linear limpo antes de criar um Pull Request. Após o rebase, todos os commits são organizados sequencialmente sem commits de merge desnecessários. No entanto, rebase requer force push e não é aplicável a branches onde várias pessoas trabalham simultaneamente.
A regra de ouro do Git: não use rebase em commits que já foram enviados para o repositório compartilhado. Isso garante que o histórico no branch compartilhado permaneça inalterado e que outros desenvolvedores não encontrem commits duplicados ou perdidos. Para integrar um branch de funcionalidade ao branch principal, use merge via Pull Request.
Um processo de merge adequado é a base do desenvolvimento estável. No trabalho em equipe moderno, a fusão não é feita através do console, mas sim via Pull Request no GitHub ou Merge Request no GitLab. Um PR passa por revisão de código, verificações automáticas de CI e só então é mesclado ao branch principal.
A primeira prática — mesclar apenas depois que todas as verificações passarem. O pipeline de CI deve compilar o projeto, executar testes e verificar a qualidade do código. Se pelo menos uma verificação falhar, o merge é bloqueado. As plataformas modernas (GitHub, GitLab) têm proteção integrada: branch protection rules bloqueiam automaticamente o merge se o CI falhar.
A segunda prática — nunca mesclar código quebrado. Antes do merge, o desenvolvedor deve garantir que suas alterações não quebrem a compilação nem regressionem a funcionalidade existente. Para isso existem testes automáticos e revisão de código.
A terceira prática — limpar os branches de funcionalidade após o merge. Um branch que já foi mesclado deve ser excluído. Isso evita confusão e desordem no repositório. O GitHub oferece automaticamente a exclusão do branch após o merge de um PR, e as configurações do repositório podem ser ajustadas para exclusão automática.
Perguntas Frequentes
Um merge é a combinação de dois branches do Git em um. As alterações de um branch são transferidas para outro através de uma fusão a três vias (three-way merge). O resultado é registrado em um novo commit de merge que tem dois commits pais. Merge commit preserva informações sobre quais branches foram mesclados.
Merge cria um novo commit de merge, preservando o histórico de ramificação. Rebase reescreve o histórico movendo commits sobre outro branch sem criar um merge commit. Rebase dá um histórico linear mas requer force push. Merge é mais seguro para branches compartilhados, rebase é melhor para branches pessoais.
Abra o arquivo em conflito, encontre os marcadores <<<<<<<, ======= e >>>>>>>, selecione as alterações necessárias e remova os marcadores. Adicione o arquivo via git add e complete o merge via git merge --continue. Use git mergetool para resolução visual no VS Code ou IntelliJ IDEA.
Pull Request (ou Merge Request) é obrigatório ao mesclar um branch de funcionalidade no branch principal do projeto. Um PR passa por revisão de código de colegas e verificações automáticas de CI. Este é o padrão do desenvolvimento moderno. Push direto para o branch principal é proibido na maioria dos projetos.
Squash merge combina todos os commits de um branch de funcionalidade em um antes de mesclar. Isso dá um histórico limpo do branch principal sem commits intermediários de rascunho. Use squash merge quando um branch de funcionalidade contém muitos commits utilitários (wip, fixes) e não for necessário preservar todos os passos intermediários no histórico.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também