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.

100%
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:

(3) Direção da fusão

TEXT 📖 Somente leitura
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.

100%
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

BASH
# 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”

BASH
# 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.

100%
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

BASH
# 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

BASH
# 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

BASH
# 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

BASH
# 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

BASH
# 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

BASH
# 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

TEXT 📖 Somente leitura
<<<<<<< HEAD
Content of the current branch(HEAD)
=======
To merge the contents of the branches
>>>>>>> feature

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

BASH
# 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

BASH
# 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

BASH
# 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

BASH
# 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

BASH
# 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

BASH
# 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 add para marcar o conflito como resolvido e, por fim, use git commit para 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 --abort para cancelar a fusão e voltar ao estado anterior à fusão. Se você já tiver resolvido alguns dos conflitos, também pode usar git reset --merge para 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


📝 Exercícios

  1. 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”.

  2. 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.

  3. 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.

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%