Git: Um guia detalhado sobre fusão de código e resolução de…
Uma fusão é o processo de combinar alterações de diferentes ramos. Por meio da fusão, as equipes podem desenvolver diferentes funcionalidades em paralelo e, em seguida, integrá-las em uma única versão. Compreender os princípios da fusão e da resolução de conflitos é fundamental para a colaboração em equipe.
1. Conceitos básicos sobre fusões
(1) O que é uma fusão?
Uma fusão é o processo de aplicar alterações de um branch a outro. O Git tenta fundir as alterações automaticamente, mas podem surgir conflitos quando as alterações nos dois branches afetam o mesmo local.
graph TB
A[mainBranch] --> B[MergefeatureBranch]
B --> C{Is there a conflict??}
C -->|No conflict| D[Automatic merge successful]
C -->|There is a conflict| E[Resolve conflicts manually]
E --> F[Mark the conflict as resolved]
F --> G[Complete the merger]
style D fill:#d4edda
style E fill:#fff3cd
(2) Tipos de fusões
O Git suporta dois tipos de mesclagem:
- Mesclagem rápida: Se não houver novos commits no ramo de destino, o ponteiro é movido diretamente
- Mesclagem de três vias: ambas as ramificações têm novos commits; crie um commit de mesclagem
(3) Direção da fusão
git merge feature # Merge feature into the current branch
Uma fusão sempre incorpora o branch especificado ao branch atual; portanto, certifique-se de verificar o branch atual antes de realizar a fusão.
2. Fusão com avanço rápido
(1) O princípio da fusão por avanço rápido
Quando o branch de destino (como main) não possui novos commits, mas o branch a ser mesclado (como feature) possui novos commits, o Git pode simplesmente avançar o ponteiro main; isso é chamado de mesclagem fast-forward.
graph LR
subgraph Before the merger
C1[SubmitC1] --> C2[SubmitC2]
C2 --> C3[SubmitC3]
main1[main] --> C2
feature1[feature] --> C3
end
subgraph After the merger
C4[SubmitC1] --> C5[SubmitC2]
C5 --> C6[SubmitC3]
main2[main] --> C6
feature2[feature] --> C6
end
style main1 fill:#fff3cd
style main2 fill:#d4edda
(2) Realizar uma fusão “fast-forward”
▶ Exemplo: Fusão com avanço rápido
# View Current Status
git log --oneline --graph --all
# Output:
# * d4e5f6g (feature) Add feature
# * a1b2c3d (HEAD -> main) Initial commit
# Switch tomainBranch
git switch main
# MergefeatureBranch
git merge feature
# Output:
# Updating a1b2c3d..d4e5f6g
# Fast-forward
# feature.js | 1 +
# 1 file changed, 1 insertion(+)
# create mode 100644 feature.js
# View the merge results
git log --oneline --graph --all
# Output:
# * d4e5f6g (HEAD -> main, feature) Add feature
# * a1b2c3d Initial commit
(3) Desativar a fusão por avanço rápido
Às vezes, mesmo quando é possível fazer mesclagens com avanço rápido, eu quero criar um commit de mesclagem para preservar o histórico do branch.
▶ Exemplo: Desativando a fusão “Fast-Forward”
# Usage--no-ffDisable Fast-Forward Merge
git merge --no-ff feature
# Output:
# Merge made by the 'ort' recursive strategy.
# feature.js | 1 +
# 1 file changed, 1 insertion(+)
# create mode 100644 feature.js
# View History
git log --oneline --graph --all
# Output:
# * a1b2c3d (HEAD -> main) Merge branch 'feature'
# |\
# | * d4e5f6g (feature) Add feature
# |/
# * h7i8j9k Initial commit
3. Fusão entre três partes
(1) O Princípio da Fusão Tripla
Quando ambos os ramos têm novos commits, o Git precisa encontrar um ancestral comum (a base de mesclagem) e, em seguida, realizar uma mesclagem tripla.
graph TB
A[Common Ancestor<br/>Merged Base] --> B[mainBranch Commit]
A --> C[featureBranch Commit]
B --> D[Three-Party Merger]
C --> D
D --> E[Merge Commit]
style A fill:#fff3cd
style E fill:#d4edda
(2) Realizar uma fusão entre três partes
▶ Exemplo: Fusão entre três partes
# View Branch Status
git log --oneline --graph --all
# Output:
# * d4e5f6g (feature) Feature work
# | * a1b2c3d (HEAD -> main) Main work
# |/
# * h7i8j9k Initial commit
# MergefeatureBranch
git merge feature
# Output:
# Merge made by the 'ort' recursive strategy.
# feature.js | 1 +
# 1 file changed, 1 insertion(+)
# View the merge results
git log --oneline --graph --all
# Output:
# * k9l0m1n (HEAD -> main) Merge branch 'feature'
# |\
# | * d4e5f6g (feature) Feature work
# * | a1b2c3d Main work
# |/
# * h7i8j9k Initial commit
(3) Visualizar a base de mesclagem
▶ Exemplo: Encontrando um ancestral comum
# Find the common ancestor of two branches
git merge-base main feature
# Output:
# h7i8j9k
# View the content to be merged
git diff $(git merge-base main feature) feature
# Or use the three-point syntax
git diff main...feature
4. Resolução de conflitos de mesclagem
(1) As origens do conflito
Quando dois branches modificam o mesmo local no mesmo arquivo, o Git não consegue mesclá-los automaticamente, o que resulta em um conflito.
▶ Exemplo: Conflito
# Modifying Files on a Branch
echo "main content" > file.js
git add file.js
git commit -m "Main modification"
# Switch tofeatureBranch
git switch feature
# Modify the same location in the same file
echo "feature content" > file.js
git add file.js
git commit -m "Feature modification"
# Switch back tomainCombine and Merge
git switch main
git merge feature
# Output:
# Auto-merging file.js
# CONFLICT (content): Merge conflict in file.js
# Automatic merge failed; fix conflicts and then commit the result.
(2) Visualizar o status do conflito
▶ Exemplo: Análise de conflitos
# View Status
git status
# Output:
# On branch main
# You have unmerged paths.
# (fix conflicts and run "git commit")
#
# Unmerged paths:
# (use "git add <file>..." to mark resolution)
# both modified: file.js
# View Conflicting Files
cat file.js
# Output:
# <<<<<<< HEAD
# main content
# =======
# feature content
# >>>>>>> feature
# View Conflict Details
git diff
# Output:
# <<<<<<< HEAD
# -main content
# =======
# -feature content
# >>>>>>> feature
(3) Resolução de conflitos
▶ Exemplo: Resolução manual de conflitos
# Editing Files with Conflicts,Select the content to keep
cat file.js
# Method1:RetainmainChanges to
# main content
# Method2:RetainfeatureChanges to
# feature content
# Method3:Merge the changes from both
# main content
# feature content
# Mark the conflict as resolved
git add file.js
# Complete the merger
git commit
# Output:
# [main d4e5f6g] Merge branch 'feature'
(4) Uso de ferramentas para resolver conflitos
▶ Exemplo: Como usar a ferramenta de mesclagem
# Using a Graphical Merge Tool
git mergetool
# Using Specific Tools
git mergetool --tool=vimdiff
# View available merge tools
git mergetool --tool-help
# UsagecheckoutSelect a Version
git checkout --ours file.js # Select the current branch version
git checkout --theirs file.js # Select a branch version to merge
(5) Explicação detalhada dos marcadores de conflito
<<<<<<< HEAD
Content of the current branch(HEAD)
=======
To merge the contents of the branches
>>>>>>> feature
<<<<<<< HEAD: Início do conteúdo do ramo atual=======: Separador; o ramo atual está acima dele, e o ramo a ser mesclado está abaixo dele>>>>>>> feature: Fim do conteúdo a ser incorporado do ramo
5. Estratégia de fusão
(1) Opções de estratégia de mesclagem
O Git oferece suporte a diversas estratégias de mesclagem:
| Estratégia | Descrição | Caso de uso |
|---|---|---|
| recursivo (padrão) | Fusão recursiva de três vias | Na maioria dos casos |
| octopus | Fusão de vários ramos | Utilizado automaticamente ao fundir vários ramos |
| nossa | Ignorar outros ramos | Manter o ramo atual |
| o deles | Ignorar o branch atual | Manter o branch a ser mesclado |
| resolução | Fusão simples de três vias | Casos especiais |
▶ Exemplo: Como usar uma estratégia de fusão
# UsagerecursiveStrategy(Default)
git merge feature
# UsageoursStrategy(IgnorefeatureChanges to)
git merge -s ours feature
# UsagerecursiveStrategy Options
git merge -X ours feature # In case of a conflict, prioritize the current branch
git merge -X theirs feature # In the event of a conflict, prioritize the branch to be merged
git merge -X ignore-space-change feature # Ignore changes in whitespace
(2) Compactação e fusão
Compactar vários commits em um único commit e, em seguida, mesclá-los.
▶ Exemplo: Compactar e mesclar
# Compress and Merge
git merge --squash feature
# View Status
git status
# Output:
# Changes to be committed:
# new file: feature1.js
# new file: feature2.js
# Commit the compressed changes
git commit -m "Merge feature branch (squashed)"
# Advantages:Keep the main branch history clean
# Disadvantages:LostfeatureDetailed History of the Branch
(3) Apenas mesclar, não confirmar
▶ Exemplo: Visualização da fusão
# Merge but do not commit automatically
git merge --no-commit feature
# View the merge results
git status
git diff --staged
# If you're satisfied,Manual Submission
git commit -m "Merge feature branch"
# If you are not satisfied,Cancel Merge
git merge --abort
6. Operações de fusão
(1) Suspensão da fusão
▶ Exemplo: Cancelamento de uma fusão em andamento
# Conflicts Arising from Mergers
git merge feature
# CONFLICT (content): Merge conflict in file.js
# Cancel Merge,Restore to the state prior to the merge
git merge --abort
# Or usereset
git reset --merge
(2) Visualizar histórico de mesclagens
▶ Exemplo: Visualizar um commit mesclado
# View All Merge Commits
git log --merges --oneline
# Output:
# d4e5f6g Merge branch 'feature'
# a1b2c3d Merge branch 'develop'
# View Unmerged Commits
git log --no-merges --oneline
# View details of the merge
git show --stat d4e5f6g
(3) Revogar a fusão
▶ Exemplo: Desfazendo uma fusão concluída
# Undo the Last Merge(Merge requests are still available)
git reset --hard HEAD~1
# UsagerevertRevoke Merger(Create a New Commit)
git revert -m 1 HEAD
# -m 1 Indicates that the first parent commit is being preserved(mainBranch)
# View Results
git log --oneline --graph
❓ Perguntas Frequentes
P: Qual é a diferença entre uma fusão fast-forward e uma fusão de três vias?
R: Uma fusão por avanço rápido é realizada quando o ramo de destino não possui novos commits; ela simplesmente move o ponteiro sem criar um commit de fusão. Uma fusão tripla é realizada quando ambos os ramos possuem novos commits; ela identifica um ancestral comum para a fusão e cria um commit de fusão.
P: Como faço para resolver conflitos de mesclagem?
R: Edite o arquivo com conflitos, remova os marcadores de conflito (<<<<<<<, =======, >>>>>>>), mantenha o conteúdo necessário, use
git addpara marcar o conflito como resolvido e, por fim, usegit commitpara concluir a fusão.
P: Quando devo usar a opção --no-ff?
R: Use isso quando quiser preservar o histórico do branch e indicar claramente que se trata de uma operação de mesclagem. Geralmente é usado ao mesclar um branch de recurso no branch principal, para que o ponto de mesclagem fique visível no histórico.
P: Como faço para cancelar uma fusão que está em andamento?
R: Use
git merge --abortpara cancelar a fusão e voltar ao estado anterior à fusão. Se você já tiver resolvido alguns dos conflitos, também pode usargit reset --mergepara reiniciar.
P: Qual é a diferença entre uma fusão do tipo “squash” e uma fusão comum?
R: Uma fusão “squash” comprime todos os commits de um ramo em um único commit, sem preservar o histórico detalhado do ramo. A vantagem é que o histórico do ramo principal permanece conciso; a desvantagem é que o histórico de commits do ramo e as informações contextuais são perdidos.
📖 Resumo
- Uma fusão é o processo de integrar alterações de um branch em outro.
- Fusão por avanço rápido: se não houver novos commits no ramo de destino, basta mover o ponteiro
- Fusão de três ramificações: ambas as ramificações têm novos commits; crie um commit de fusão
- Resolução de conflitos: edite o arquivo com conflitos, remova os marcadores e mantenha o conteúdo que você precisa
- Estratégias de mesclagem: recursiva (padrão), a nossa, a deles, squash, etc.
- Operações de mesclagem: --abort para cancelar, --no-commit para visualizar, revert para desfazer
📝 Exercícios
-
Exercício básico: Crie dois branches, modifique arquivos diferentes em cada um deles e, em seguida, faça a fusão para observar a diferença entre uma fusão “fast-forward” e uma fusão “three-way”.
-
Exercício avançado: Simule um cenário de conflito: faça alterações no mesmo local do mesmo arquivo em dois ramos; ao fazer a fusão, ocorre um conflito; resolva manualmente o conflito e conclua a fusão.
-
Desafio: Faça a fusão de branches utilizando diferentes estratégias de fusão (--no-ff, --squash, -X ours, etc.) e compare os resultados e os casos de uso adequados para cada estratégia.