0%
Tutorial 7 de 10
70% concluído

Resolução de conflitos

Aprenda a identificar e resolver os conflitos de merge que surgem durante a colaboração.

Resolução de conflitos

Os conflitos no Git são inevitáveis no desenvolvimento colaborativo. Este tutorial vai ensinar você a entender, identificar e resolver conflitos de merge com eficiência, para manter um workflow fluido em equipe.

O que é um conflito no Git?

Um conflito ocorre quando o Git não consegue mesclar automaticamente as alterações de duas branches porque elas modificam as mesmas linhas de código de maneira incompatível.

mainfeature-afeature-bInitialModify line 5Modify line 5 differentlyCONFLICT!

Tipos de conflitos

1. Conflitos de conteúdo

Modificações simultâneas das mesmas linhas:

# Branche A modifie :
function greet() {
    return "Hello World!";
}

# Branche B modifie :
function greet() {
    return "Bonjour le monde!";
}

2. Conflitos de renomeação

# Branche A : renomme file.txt en document.txt
# Branche B : modifie le contenu de file.txt
# Résultat : Git ne sait pas quoi faire

3. Conflitos de exclusão

# Branche A : supprime file.txt
# Branche B : modifie file.txt
# Résultat : Conflit de suppression/modification

Anatomia de um conflito

Marcadores de conflito

<<<<<<< HEAD
function calculateTotal(items) {
    return items.reduce((sum, item) => sum + item.price, 0);
}
=======
function calculateTotal(items) {
    let total = 0;
    for (let item of items) {
        total += item.price;
    }
    return total;
}
>>>>>>> feature/new-calculation

Explicação dos marcadores:

  • <<<<<<< HEAD: início da sua versão (branch atual)
  • =======: separador entre as versões
  • >>>>>>> feature/new-calculation: fim da versão da outra branch

Identificar os conflitos

Comandos de diagnóstico

# Voir l'état des conflits
git status

# Lister les fichiers en conflit
git diff --name-only --diff-filter=U

# Voir les détails des conflits
git diff

# Voir les conflits avec plus de contexte
git diff --conflict=diff3

Saída típica do git status

On branch main
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   src/calculator.js
        both modified:   README.md

no changes added to commit (use "git add" or "git commit -a")

Estratégias de resolução

1. Resolução manual

# 1. Identifier les fichiers en conflit
git status

# 2. Ouvrir le fichier et éditer manuellement
# Supprimer les marqueurs <<<<<<, =======, >>>>>>>
# Garder le code désiré

# 3. Marquer comme résolu
git add fichier-resolu.js

# 4. Finaliser la fusion
git commit

2. Escolher uma versão completa

# Garder votre version (HEAD)
git checkout --ours fichier.js
git add fichier.js

# Garder leur version
git checkout --theirs fichier.js
git add fichier.js

# Finaliser
git commit

3. Ferramentas de merge

# Configurer un outil de merge
git config --global merge.tool vimdiff

# Lancer l'outil
git mergetool

# Autres outils populaires
git config --global merge.tool vscode
git config --global merge.tool kdiff3
git config --global merge.tool meld

Resolução passo a passo

Exemplo prático completo

# Situation : Conflit lors d'un merge
git merge feature/user-profile
# Auto-merging src/user.js
# CONFLICT (content): Merge conflict in src/user.js
# Automatic merge failed; fix conflicts and then commit the result.

# 1. Examiner le conflit
git status
cat src/user.js

Conteúdo do arquivo com conflito:

class User {
    constructor(name, email) {
        this.name = name;
        this.email = email;
<<<<<<< HEAD
        this.id = Math.random().toString(36);
        this.createdAt = new Date();
=======
        this.id = generateUniqueId();
        this.timestamp = Date.now();
>>>>>>> feature/user-profile
    }
}
# 2. Résoudre le conflit (édition manuelle)
# Décider de combiner les deux approches

Resolução:

class User {
    constructor(name, email) {
        this.name = name;
        this.email = email;
        this.id = generateUniqueId(); // Utiliser la fonction plus robuste
        this.createdAt = new Date();  // Garder le format Date
        this.timestamp = Date.now();  // Ajouter aussi le timestamp
    }
}
# 3. Marquer comme résolu
git add src/user.js

# 4. Vérifier que tous les conflits sont résolus
git status

# 5. Finaliser le merge
git commit -m "Merge feature/user-profile

Resolved conflicts in user.js by combining both ID generation
approaches and keeping both timestamp formats for compatibility."

Ferramentas de resolução

VS Code

O VS Code oferece uma interface intuitiva para resolver conflitos:

// settings.json
{
    "git.mergeEditor": true,
    "merge-conflict.autoNavigateNextConflict.enabled": true
}

Funcionalidades:

  • Accept Current Change: manter a sua versão
  • Accept Incoming Change: manter a versão da outra branch
  • Accept Both Changes: combinar as duas
  • Compare Changes: ver as diferenças lado a lado

GitKraken

Interface gráfica avançada:

  • Visualização das branches e dos conflitos
  • Editor de merge integrado
  • Histórico das resoluções

Linha de comando com vimdiff

# Configuration
git config --global merge.tool vimdiff

# Utilisation
git mergetool

# Navigation dans vimdiff
# :diffget LOCAL    - Prendre la version locale
# :diffget REMOTE   - Prendre la version distante
# :diffget BASE     - Prendre la version de base

Prevenção de conflitos

Boas práticas

  1. Sincronização frequente

    # Récupérer régulièrement les changements
    git fetch origin
    git merge origin/main
  2. Branches curtas

    # Éviter les branches de longue durée
    # Merger fréquemment les petites fonctionnalités
  3. Comunicação em equipe

    # Coordonner les modifications sur les mêmes fichiers
    # Utiliser les issues GitHub pour planifier
  4. Rebase antes do merge

    git fetch origin
    git rebase origin/main
    # Résoudre les conflits un par un
    git push --force-with-lease origin feature-branch

Organização do código

// Éviter les conflits en structurant le code
// Séparer les fonctionnalités en modules distincts

// ❌ Tout dans un fichier
// app.js (500 lignes)

// ✅ Modules séparés
// auth.js
// user.js
// api.js
// utils.js

Conflitos avançados

Conflitos durante o rebase

# Démarrer un rebase
git rebase main

# En cas de conflit
# 1. Résoudre le conflit
# 2. Ajouter les fichiers résolus
git add .

# 3. Continuer le rebase
git rebase --continue

# Ou abandonner
git rebase --abort

Conflitos com cherry-pick

# Cherry-pick avec conflit
git cherry-pick abc1234

# Résoudre et continuer
git add .
git cherry-pick --continue

# Ou abandonner
git cherry-pick --abort

Conflitos de merge vs rebase

Conflitos de merge:

  • Resolvidos de uma só vez
  • Histórico preservado
  • Commit de merge criado

Conflitos de rebase:

  • Resolvidos commit por commit
  • Histórico linear
  • Nenhum commit de merge

Exercícios práticos

Exercício 1: conflito simples

# 1. Créer un dépôt de test
mkdir conflict-demo
cd conflict-demo
git init

# 2. Créer un fichier initial
echo "function greet() {
    return 'Hello';
}" > greet.js
git add greet.js
git commit -m "Initial greeting function"

# 3. Créer deux branches avec modifications conflictuelles
git checkout -b feature-french
echo "function greet() {
    return 'Bonjour';
}" > greet.js
git add greet.js
git commit -m "Add French greeting"

git checkout main
git checkout -b feature-spanish
echo "function greet() {
    return 'Hola';
}" > greet.js
git add greet.js
git commit -m "Add Spanish greeting"

# 4. Merger et résoudre le conflit
git checkout main
git merge feature-french
git merge feature-spanish
# Conflit attendu !

# 5. Résoudre en combinant les langues
echo "function greet(language = 'en') {
    const greetings = {
        'en': 'Hello',
        'fr': 'Bonjour',
        'es': 'Hola'
    };
    return greetings[language] || greetings['en'];
}" > greet.js

git add greet.js
git commit -m "Resolve conflict by supporting multiple languages"

Exercício 2: conflito complexo com vários arquivos

# 1. Créer un projet avec plusieurs fichiers
echo "# My App" > README.md
echo "const version = '1.0.0';" > version.js
echo "function add(a, b) { return a + b; }" > math.js
git add .
git commit -m "Initial project setup"

# 2. Branche A : Modifications multiples
git checkout -b feature-updates
echo "# My Awesome App
Version 2.0 with new features!" > README.md
echo "const version = '2.0.0';" > version.js
echo "function add(a, b) { 
    if (typeof a !== 'number' || typeof b !== 'number') {
        throw new Error('Invalid input');
    }
    return a + b; 
}" > math.js
git add .
git commit -m "Update to version 2.0 with validation"

# 3. Branche B : Modifications différentes
git checkout main
git checkout -b feature-improvements
echo "# My App
Now with better performance!" > README.md
echo "const version = '1.1.0';" > version.js
echo "function add(a, b) { 
    // Optimized addition
    return Number(a) + Number(b); 
}" > math.js
git add .
git commit -m "Performance improvements v1.1"

# 4. Merger et résoudre tous les conflits
git checkout main
git merge feature-updates
git merge feature-improvements
# Résoudre chaque fichier individuellement

Estratégias de equipe

Workflow com conflitos mínimos

# 1. Feature branches courtes
git checkout -b feature/small-change
# ... développement rapide ...
git push origin feature/small-change
# ... PR et merge rapide ...

# 2. Rebase avant PR
git fetch origin
git rebase origin/main
git push --force-with-lease origin feature/small-change

# 3. Merge fréquent de main
git checkout feature/long-running
git merge origin/main
# Résoudre les conflits au fur et à mesure

Comunicação dos conflitos

# Template de message pour conflit résolu
## Conflit résolu dans PR #123

**Fichiers affectés :**
- src/user.js
- src/auth.js

**Nature du conflit :**
Modifications simultanées des méthodes d'authentification

**Résolution choisie :**
Combinaison des deux approches :
- Garde la validation de feature-a
- Intègre l'optimisation de feature-b

**Tests effectués :**
- [ ] Tests unitaires passent
- [ ] Tests d'intégration OK
- [ ] Validation manuelle

cc @team-lead @reviewer

Solução de problemas avançada

Desfazer uma resolução de conflito

# Si vous avez fait une erreur dans la résolution
git reset --hard HEAD~1  # Annule le commit de merge
git merge feature-branch  # Recommence le merge

Ver o histórico dos conflitos

# Voir les merges précédents
git log --merges --oneline

# Voir les détails d'un merge
git show commit-hash

# Voir les conflits d'un merge spécifique
git log --cc commit-hash

Resolução automática

# Configurer des stratégies de merge
git config merge.ours.driver true  # Toujours garder notre version
git config merge.theirs.driver "cp %B %A"  # Toujours garder leur version

# Dans .gitattributes
*.generated merge=ours
*.config merge=theirs

Recursos adicionais

Ferramentas recomendadas

  • Beyond Compare: ferramenta profissional de diff/merge
  • P4Merge: gratuita e eficiente
  • Meld: código aberto, multiplataforma
  • KDiff3: merge de 3 vias

Documentação

Conclusão

A resolução de conflitos é uma habilidade essencial para qualquer desenvolvedor que trabalha em equipe. Com prática e as ferramentas certas, os conflitos passam a ser uma parte normal e gerenciável do workflow de desenvolvimento.

No próximo tutorial, vamos explorar os workflows avançados do Git usados em equipes profissionais.


Tempo de leitura estimado: 30 minutos
Nível: Intermediário
Etapa anterior: Colaboração com o GitHub
Próxima etapa: Workflows avançados do Git