git merge
Juntar dois ou mais históricos de desenvolvimento
O comando 'git merge' incorpora na branch atual as mudanças dos commits indicados (desde que os históricos se separaram da branch atual). O Git faz um merge “fast-forward” quando possível (quando a branch atual é ancestral da branch mesclada) ou cria um “commit de merge” quando os históricos divergiram. Se houver conflitos entre as branches, o Git para e pede que você os resolva antes de concluir o merge.
Sinopse
git merge [--no-ff | --ff-only] [--squash] [--no-commit] [-m <msg>] [--allow-unrelated-histories] [<commit>...]
git merge (--continue | --abort | --quit)Opções
Escolhendo a opção certa
Estratégias de merge
Como controlar o tipo de merge que o Git faz
| Comando | Cria commit de merge | Preserva o histórico | Ideal para |
|---|---|---|---|
git merge (default) | Se divergiram | Sim | Integração normal de funcionalidade |
git merge --no-ff | Sempre | Sim | Documentar merges de funcionalidades |
git merge --ff-only | Nunca | Só linear | Garantir um histórico limpo |
git merge --squash | Não (commit comum) | Não (achatado) | Branch main limpa |
Lidar com conflitos
O que fazer quando um merge tem conflitos
| Comando | Ação | Mantém o trabalho | Quando usar |
|---|---|---|---|
(resolve manually) | Editar arquivos, git add | Sim | Precisa de partes dos dois lados |
--continue | Concluir o merge | Sim | Depois de resolver os conflitos |
--abort | Cancelar o merge | Estado anterior ao merge | Não está pronto para resolver agora |
checkout --ours/--theirs | Escolher um lado | Uma versão só | Um lado está claramente certo |
merge ou rebase
Dois jeitos de integrar mudanças - com prós e contras diferentes
| Comando | Histórico | Resolução de conflitos | Ideal para |
|---|---|---|---|
git merge | Preserva todos os commits | Uma vez | Branches compartilhadas, PRs |
git rebase | Reescreve de forma linear | Por commit | Limpeza local, branches privadas |
git merge --squash | Um só commit | Uma vez | Funcionalidade com histórico bagunçado |
Controlar o commit
Opções para personalizar o commit de merge
| Comando | Faz commit automaticamente | Caso de uso |
|---|---|---|
git merge feature | Sim (se não houver conflitos) | Merge padrão |
git merge --no-commit | Não (preparado) | Revisar antes do commit |
git merge -m "msg" | Sim (ignorado no fast-forward) | Commits de merge descritivos |
git merge --squash | Não (precisa fazer commit) | Juntar todos os commits em um |
Exemplos de fluxos de trabalho
git checkout mainTrocar para a branch main
git pull origin mainPegar as mudanças mais recentes do remoto
git merge --no-ff feature-branchMesclar a funcionalidade com um commit de merge para o histórico
git push origin mainEnviar as mudanças mescladas para o remoto
git branch -d feature-branchExcluir a branch de funcionalidade mesclada
git merge featureTentar o merge (aparecem conflitos)
git statusVer quais arquivos têm conflitos
(edit conflicted files)Procurar os marcadores <<<<<<< e resolver à mão
git add <resolved-files>Preparar os arquivos resolvidos
git merge --continueConcluir o merge com um commit
git checkout mainTrocar para a branch main
git merge --squash feature-branchJuntar todos os commits em mudanças preparadas
git commit -m "Add feature X"Criar um único commit limpo com todas as mudanças
git branch -D feature-branchForçar a exclusão da branch de funcionalidade
git merge featureComeçar o merge (surgem problemas)
git statusVer o estado com conflitos
git merge --abortCancelar e voltar ao estado anterior ao merge
git statusConfirmar que voltou a um estado limpo
Solução de problemas
CONFLICT (content): Merge conflict in file.js
Causa: As duas branches modificaram as mesmas linhas do arquivo
Abra o arquivo, procure os marcadores <<<<<<<, resolva e depois git add e git merge --continue
fatal: refusing to merge unrelated histories
Causa: As branches não têm ancestral comum (repositórios separados)
Use git merge --allow-unrelated-histories se quiser mesmo juntar projetos separados
Already up to date
Causa: A branch que você está mesclando já está incluída na branch atual
Nada a fazer - a sua branch já contém todos os commits da outra
error: Your local changes to the following files would be overwritten by merge
Causa: Você tem mudanças sem commit que conflitam com o merge
Faça commit das mudanças, guarde-as com stash (git stash) ou descarte-as antes do merge
O merge foi feito, mas eu queria revisar antes
Causa: O Git fez o commit do merge automaticamente
Da próxima vez use --no-ff --no-commit. Para refazer: git reset --merge ORIG_HEAD e faça o merge de novo com --no-commit
Dicas e armadilhas
Boas práticas
- ✓Sempre faça pull das mudanças mais recentes antes do merge para diminuir conflitos
- ✓Use --no-ff em branches de funcionalidade para preservar o contexto do merge no histórico
- ✓Escreva mensagens de merge descritivas que expliquem o que foi integrado
- ✓Exclua as branches de funcionalidade depois do merge para manter o repositório limpo
- ✓Teste o código depois do merge e antes do push para garantir que nada quebrou
- ✓Use git merge --abort se não estiver pronto para resolver conflitos - não deixe um merge pela metade
- ✓Em branches de longa duração, mescle a main na sua branch de funcionalidade de tempos em tempos para reduzir os conflitos do merge final
Erros comuns
- ✗Fazer merge sem antes puxar as mudanças mais recentes do remoto. Sempre rode 'git pull' antes do merge para evitar conflitos.
- ✗Preparar arquivos que ainda têm marcadores de conflito. O Git bloqueia commits enquanto há caminhos não mesclados, mas assim que você faz 'git add' em um arquivo ele entra no commit com os marcadores <<<<<<< do jeito que estão.
- ✗Usar merges fast-forward em branches de funcionalidade perde o histórico da branch. Use '--no-ff' para preservar o contexto.
- ✗Rodar 'git merge --abort' depois de resolver conflitos à mão perde todo o trabalho de resolução.
- ✗Fazer merge na branch errada. Sempre confira com 'git branch' que você está na branch de destino certa antes do merge.
Perguntas frequentes
O merge preserva o histórico e cria um commit de merge. O rebase reescreve o histórico para ficar linear. Use merge em branches compartilhadas e rebase para limpeza local.
Use --no-ff ao mesclar branches de funcionalidade na main. Ele cria um commit de merge que registra quando a funcionalidade foi integrada, mesmo que o fast-forward fosse possível.
Se não foi enviado: git reset --hard ORIG_HEAD (funciona também para fast-forwards; descarta mudanças sem commit). Se foi enviado: git revert -m 1 <merge-commit> para criar um commit novo que desfaz o merge.
O fast-forward acontece quando a sua branch não tem commits novos desde o ponto de separação. O Git só avança o ponteiro em vez de criar um commit de merge.
Abra os arquivos em conflito, procure os marcadores <<<<<<<, edite para ficar com o código que quer, remova os marcadores, depois faça git add nos arquivos e git merge --continue.
O merge comum preserva todo o histórico de commits. O squash merge junta tudo em um único commit. Use squash quando a branch de funcionalidade tiver commits WIP bagunçados que você não quer na main.