roselletabuena/résolution-conflits-git

Résoudre correctement les conflits de fusion, de rebase, de cherry-pick, de revert ou de stash — comprendre l'intention de chaque côté, les combiner plutôt que d'en choisir un, vérifier que le résultat compile, et poursuivre l'opération.

Qu'est-ce que résolution-conflits-git ?

Cette compétence aide les développeurs et les agents IA à résoudre correctement les conflits Git (fusion, rebase, cherry-pick, revert, stash pop) en comprenant l'intention de chaque côté et en combinant les modifications plutôt qu'en choisir une seule. Elle explique comment identifier l'opération en cours (les rôles de "ours" et "theirs" diffèrent entre merge et rebase), visualiser le conflit complet (y compris l'ancêtre commun via zdiff3), et résoudre en combinant intelligemment les changements (ex : une fonction doit prendre à la fois un paramètre tax_rate et discount ajoutés par des côtés différents). Elle couvre les cas spéciaux comme les fichiers générés (package-lock.json, go.sum) et les fichiers binaires, et insiste sur la vérification (git diff --check, compilation, tests) avant de poursuivre. La compétence fournit des garde-fous : ne jamais prendre un côté en entier à la légère (cela jette le travail de quelqu'un), ne pas abandonner un rebase demandé sans raison, ne pas pousser sans demande explicite, et signaler chaque fichier conflictuel avec ce que chaque côté a fait. Elle est conçue pour Claude Code, Cursor, Codex et tout outil d'agent IA utilisant Git.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/roselletabuena/skills/tree/HEAD/plugins/git-workflows/skills/git-conflict-resolution

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Résolution des conflits

Un conflit signifie que Git a trouvé deux modifications au même endroit et refuse de deviner. Une résolution est une décision sur l'intention, et la valeur par défaut sûre est de conserver l'intention des deux côtés. Résoudre en supprimant un côté fait disparaître les marqueurs mais aggrave le problème : la compilation passe toujours, et le changement d'un collègue a disparu.

1. Savoir dans quelle opération vous êtes – ours et theirs en dépendent

git status                  # "rebase in progress" / "You have unmerged paths" / "cherry-pick in progress"
OpérationCôté --ours / HEADCôté --theirs
mergela branche sur laquelle vous êtesla branche en cours de fusion
rebasela branche sur laquelle vous rebasez (amont)votre propre commit en cours de rejeu
cherry-pick, revert, stash popla branche sur laquelle vous êtesle commit en cours d'application

La ligne rebase est le piège. Pendant git rebase main, "ours" est main et "theirs" est le travail de l'utilisateur, l'inverse d'une fusion. git checkout --theirs file dans un rebase conserve votre modification et jette celle de l'amont. Relisez ce tableau avant d'utiliser l'un ou l'autre drapeau.

2. Voir tout le conflit, pas seulement les marqueurs

git diff --name-only --diff-filter=U        # fichiers non fusionnés
git status                                   # le type : both modified / deleted by us / both added
git config merge.conflictStyle zdiff3        # affiche aussi l'ancêtre commun (git 2.35+ ; utilisez diff3 sur les versions plus anciennes)
git checkout --conflict=zdiff3 -- <file>     # ré-affiche UN fichier avec la base visible (écarte les modifications déjà faites)

Avec la base visible, les marqueurs ont trois parties : votre côté, l'original, leur côté. La plupart des conflits apparents deviennent évidents quand on peut voir ce que chaque côté a changé à partir de.

Pour comprendre pourquoi chaque côté a changé :

git log --merge -p -- <file>                 # commits des deux côtés touchant le fichier (fusion ou rebase en cours)
git show REBASE_HEAD                          # pendant un rebase : le commit en cours de rejeu
git show :1:<file>  :2:<file>  :3:<file>     # base, "ours", "theirs" sous forme de fichiers complets

Lisez les messages de commit. Une résolution que vous ne pouvez pas expliquer en une phrase par côté est une supposition.

3. Résoudre en combinant

  • Les deux côtés ont modifié les mêmes lignes pour des raisons différentes – écrivez la version qui fait les deux. Par exemple, un côté a ajouté un paramètre tax_rate et l'autre un paramètre discount : la fonction résolue prend les deux et les applique tous les deux.
  • Un côté a déplacé ou renommé, l'autre a modifié – appliquez la modification au nouvel emplacement. Ne gardez pas l'ancien fichier et le nouveau.
  • Supprimé par un côté, modifié par l'autre – c'est une véritable décision, pas mécanique. Découvrez pourquoi il a été supprimé ; si la modification compte toujours, elle doit être reportée, sinon la suppression gagne. Demandez à l'utilisateur si ce n'est pas clair.
  • Fichiers générés et fichiers de verrouillage (package-lock.json, poetry.lock, go.sum, snapshots, sortie compilée) – ne faites pas de fusion manuelle. Prenez un côté, puis régénérez avec l'outil (npm install, poetry lock, go mod tidy, la commande de snapshot).
  • Fichiers binaires – il n'y a pas de fusion ; choisissez un côté délibérément (gardez le tableau ci-dessus à l'esprit) et dites-le.

Le texte peut fusionner proprement et être quand même faux : si un côté a renommé une fonction et l'autre a ajouté un appel à l'ancien nom, Git ne voit pas de conflit. C'est pourquoi l'étape 4 inclut la compilation.

Les drapeaux globaux cachent des décisions. git checkout --ours ., -X ours / -X theirs (qui résolvent chaque bloc conflictuel vers un côté) et -s ours (qui jette complètement l'autre branche) jettent chacun du travail sans le regarder. Utilisez-les uniquement lorsque l'utilisateur a demandé exactement cela et sait ce qui est abandonné.

4. Vérifier, puis continuer

git diff --check                              # échoue sur les marqueurs de conflit restants et les erreurs d'espacement
grep -rnE '^(<<<<<<<|=======|>>>>>>>)' .      # ceinture et bretelles, dans les fichiers que git ne vérifie pas avec diff-check
# compiler et exécuter les tests les plus rapides et pertinents
git add <fichiers-résolus>

Continuez avec la commande correspondante. Ajoutez GIT_EDITOR=true là où un éditeur s'ouvrirait, car un éditeur bloque dans un shell non interactif :

git merge --continue            # ou : git commit --no-edit
GIT_EDITOR=true git rebase --continue
GIT_EDITOR=true git cherry-pick --continue

Un rebase rejoue les commits un par un, il peut donc s'arrêter à nouveau sur le commit suivant. Répétez la boucle. Résolvez au premier commit où un conflit apparaît ; les suivants peuvent être le même conflit qui se rejoue.

Si les tests échouent après la résolution, l'échec est une information sur la résolution. Ne continuez pas au-delà et ne "corrigez" pas en modifiant les tests tant que vous ne savez pas quel comportement le test protège.

5. Quand s'arrêter et demander

Arrêtez-vous plutôt que de deviner quand :

  • les deux côtés ont modifié la logique métier de manière incompatible (deux règles fiscales différentes, deux politiques de réessai différentes) ;
  • vous ne pouvez pas dire en une phrase pourquoi chaque côté a fait son changement ;
  • la résolution fait échouer un test et la cause n'est pas claire.

Énoncez les deux intentions, dites ce que vous choisiriez et pourquoi, et laissez l'utilisateur décider. Tout avant --continue est réversible : git merge --abort, git rebase --abort, git cherry-pick --abort ramènent l'arbre à son état initial.

Conflits répétés

Pour un long rebase où le même conflit revient, ou une branche qui est fusionnée et abandonnée à plusieurs reprises :

git config rerere.enabled true      # enregistre chaque résolution et la rejoue la prochaine fois
git rerere diff                      # ce qui a été enregistré
git rerere forget-path <file>        # abandonne une résolution enregistrée qui était erronée

rerere réapplique une résolution sans demander, donc une mauvaise se propage. Après un conflit résolu par rerere, vérifiez toujours le résultat.

Quand une branche est ancienne et loin derrière, fusionner le tronc une fois signifie généralement un seul tour de conflits ; rebaser les rejoue par commit. Ce choix appartient à l'utilisateur.

Garde-fous

  • Ne résolvez jamais en prenant un côté en entier pour faire disparaître les conflits. L'autre côté est le travail de quelqu'un.
  • N'abandonnez pas un rebase que l'utilisateur vous a demandé de terminer juste parce qu'il est fastidieux ; abandonnez seulement si ça tourne mal, et dites-le.
  • Ne poussez pas après avoir résolu sauf demande explicite. Un rebase nécessite un push forcé ; suivez git-safe-history-rewrite.
  • Signalez chaque fichier en conflit : ce que les deux côtés ont fait, ce que vous avez conservé, et tout ce que vous n'avez pas pu vérifier.

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

Skills associés