Usando ramificações

Git merge

Mesclagem é o jeito do Git de unificar um histórico bifurcado. O comando git merge permite que você pegue as linhas de desenvolvimento independentes criadas pelo git branch e as integre em uma ramificação única.

Observe que todos os comandos apresentados abaixo fazem o merge para o branch atual. O branch atual vai ser atualizado para refletir a mesclagem, mas o branch alvo não vai sofrer alterações. Então é importante ressaltar: o git merge é usado com frequência em conjunto com o git checkout para selecionar o branch atual e com o git branch -d para excluir o branch alvo obsoleto.

Como funciona

O Git merge vai combinar várias sequências de commits em um histórico unificado. Nos casos de uso mais frequentes, o git merge é utilizado para combinar dois branches. Os exemplos a seguir neste documento vão focar neste padrão de mesclagem de branch. Nestes cenários, o git merge pega dois indicadores de commit, em geral, as pontas do branch e encontra um commit base em comum entre eles. Assim que o Git encontra um commit base em comum, ele cria uma nova "confirmação de mesclagem" combinando as alterações de cada sequência de merge commit enfileirada.

Imagine que você tem um novo recurso de ramificação baseado na ramificação main. Agora, você quer fazer merge desse recurso de ramificação com a main.

Executar este comando faz merge do recurso especificado na ramificação atual, por exemplo, a main. O Git define o algoritmo de merge com automação (discutido abaixo).

Novo ponto central de commit de merge

Os commits de mesclagem são únicos em relação a outros commits, devido ao fato de que terem dois commits pai. Ao criar um commit de mesclagem, o Git vai tentar mesclar automaticamente os históricos separados para você. Caso o Git encontre um pedaço de dados que está alterado em ambos os históricos, ele não vai ser capaz de fazer essa combinação. Este cenário é um conflito de controle de versão, e o Git vai precisar da intervenção do usuário para continuar.

Preparação para a mesclagem

Antes de realizar uma mesclagem, existem algumas etapas de preparação para garantir que a mesclagem dê certo.

Confirmar o branch receptor

Execute o git status para ter certeza de que HEAD está apontando para a ramificação receptora do merge correta. Se necessário, execute git checkout para alterar para a ramificação receptora. Nesse caso, vamos executar git checkout main.

Buscar os commits remotos mais recentes

Verifique se a ramificação receptora e a ramificação que vai ser mesclada estão atualizadas com as alterações remotas mais recentes. Execute o comando git fetch para enviar o pull dos commits remotos mais recentes. Assim que a busca for concluída, veja se a ramificação main tem as atualizações mais recentes executando o comando git pull.

Mesclagem

Após a conclusão das etapas de "preparação para mesclagem" discutidas antes, a mesclagem pode ser iniciada executando git merge em que é o nome do branch que vai ser mesclado no branch receptor.

Mesclagem de avanço rápido

Um merge de avanço rápido pode ocorrer quando existe um caminho linear da ponta da ramificação atual até a ramificação alvo. Em vez de fazer merge de fato das ramificações, tudo o que o Git precisa fazer para integrar os históricos é mover (ou seja, fazer o "avanço rápido") a ponta da ramificação atual até a ponta da ramificação alvo. Assim, os históricos são combinados com eficiência, uma vez que todos os commits acessíveis na ramificação alvo agora estão disponíveis na atual. Por exemplo, o merge de avanço rápido de algum recurso para a ramificação main seria parecido como o seguinte:

Ponto central do recurso estava à frente do ponto central principal, e, após o avanço rápido, ambos estão no mesmo ponto central

No entanto, uma mesclagem de avanço rápido não é possível se os branches tiverem divergido. Quando não há um caminho linear para o branch alvo, o Git não tem escolha a não ser fazer a combinação por meio da mesclagem de três vias. As mesclagens de três vias usam um commit dedicado para juntar os dois históricos. A nomenclatura vem do fato de que o Git usa três commits para gerar o commit de mesclagem: as duas pontas do branch e seu ancestral em comum.


Embora você possa usar qualquer uma destas estratégias de mesclagem, muitos desenvolvedores gostam de usar mesclagens de avanço rápido (facilitadas por meio do rebase) para pequenos recursos ou atualizações de segurança, reservando as mesclagens de três vias para a integração de recursos de maior execução. No último caso, o commit de mesclagem resultante serve como uma união simbólica dos dois branches.

O primeiro exemplo demonstra uma mesclagem de avanço rápido. O código abaixo cria um branch, adiciona dois commits a ele e, então, a integra à linha principal com uma mesclagem de avanço rápido.

# Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Merge in the new-feature branch
git checkout main
git merge new-feature
git branch -d new-feature

Este é um fluxo de trabalho comum para ramificações atuais com pouco tempo de vida que são mais usadas como um desenvolvimento isolado do que uma ferramenta organizacional para recursos de maior execução.

Observe também que o Git não deve reclamar sobre o git branch -d, uma vez que o novo recurso está agora acessível na ramificação principal.

Caso você precise do commit de mesclagem durante uma mesclagem de avanço rápido para fins de manter registros, você pode executar o git merge com a opção --no-ff.

git merge --no-ff <branch>

Este comando vai mesclar o branch especificado com o branch atual, mas sempre gerando um commit de mesclagem (mesmo no caso da mesclagem de avanço rápido). Isto é útil para documentar todas as mesclagens que ocorrem no repositório.

Mesclagem de 3 vias

O próximo exemplo é bem parecido, mas requer um merge de três vias, pois a ramificação main progride enquanto o recurso está em progresso. Este é um cenário comum para recursos grandes ou quando muitos desenvolvedores estão trabalhando no projeto ao mesmo tempo.

Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Develop the main branch
git checkout main
# Edit some files
git add <file>
git commit -m "Make some super-stable changes to main"
# Merge in the new-feature branch
git merge new-feature
git branch -d new-feature

Observe que é impossível para o Git realizar um merge de avanço rápido, pois não há como mover a ramificação main até o new-feature sem retroceder.

Para a maioria dos fluxos de trabalho, o new-feature seria um recurso muito maior, que levou muito tempo para ser desenvolvido, o que explicaria os novos commits aparecendo na ramificação main nesse meio tempo. Caso a ramificação de recurso seja de fato tão pequena quanto a do exemplo acima, é provável que seja melhor fazer o rebase dela para a ramificação main e realizar um merge de avanço rápido. Assim, você evita que os commits de merge supérfluo se acumulem no histórico do projeto.

Resolução de conflitos

Se as duas ramificações que você está tentando mesclar alterarem a mesma parte do mesmo arquivo, o Git pode não conseguir decidir qual versão usar. Quando essa situação ocorre, ele para antes do commit de mesclagem para que você possa resolver os conflitos.

A parte boa do processo de mesclagem do Git é que ele usa o já conhecido fluxo de trabalho edit/stage/commit para resolver conflitos de mesclagem. Quando você encontra um conflito de mesclagem, executar o comando git status vai exibir quais arquivos precisam ser resolvidos. Por exemplo, se ambos os branches modificaram a mesma sessão de hello.py, você veria algo como o seguinte:

On branch main
Unmerged paths:
(use "git add/rm ..." as appropriate to mark resolution)
both modified: hello.py

Como os conflitos são apresentados

Quando o Git encontrar um conflito durante uma mesclagem, ele vai editar o conteúdo dos arquivos afetados com indicações visuais, marcando ambos os lados do conteúdo em conflito. Estas marcações visuais são: <<<<<<<, =======, e >>>>>>>. É útil pesquisar um projeto por estes indicadores durante uma mesclagem para encontrar onde conflitos precisam ser resolvidos.

here is some content not affected by the conflict
<<<<<<< main
this is conflicted text from main
=======
this is conflicted text from feature branch
>>>>>>> feature branch;

Em geral, o conteúdo antes do marcador ======= é o branch receptor e a parte seguinte é o branch que vai ser mesclado.

Após identificar as seções conflitantes, você pode corrigir a mesclagem como preferir. Quando você estiver pronto para concluir a mesclagem, tudo o que precisa fazer é executar git add no(s) arquivo(s) conflitante(s) para dizer ao Git que eles foram resolvidos. Em seguida, você executa um git commit normal para gerar o commit de mesclagem. É o mesmo processo de fazer o commit de um snapshot comum, o que significa que é fácil para desenvolvedores normais gerenciarem suas próprias mesclagens.

Observe que conflitos de mesclagem vão ocorrer apenas no caso da mesclagem de 3 vias. Não é possível ocorrerem alterações conflitantes em uma mesclagem de avanço rápido.

Resumo

Este documento é uma visão geral do comando git merge. A mesclagem é um processo essencial ao trabalhar com o Git. Foi abordada a mecânica interna por trás da mesclagem e as diferenças entre uma mesclagem de avanço rápido e uma mesclagem verdadeira, a de três vias. Algumas das principais conclusões são:

  1. A mesclagem do Git combina várias sequências de commits em um histórico unificado.
  2. Há duas maneiras principais do Git fazer a mesclagem: a de avanço rápido e a de três vias
  3. O Git pode fazer a mesclagem automática dos commits, a menos que haja alterações que entrem em conflito em ambas as sequências de commit.

Este documento inclui e faz referência a outros comandos Git, como: git branch, git pull e git fetch. Visite suas páginas correspondentes para obter mais informações.

Pronto para testar a ramificação?

Tente este tutorial interativo.

Comece agora mesmo