Comment comprendre et résoudre les conflits dans Git

Voilà, le mot que tout développeur déteste voir: conflit. 😱 Il n'y a tout simplement aucun moyen d'éviter les conflits de fusion occasionnels lorsque vous travaillez avec Git (ou d'autres systèmes de contrôle de version).

Mais lorsque je parle avec les développeurs, j'entends souvent qu'il y a un sentiment d' anxiété ou d' inconfort autour du sujet des conflits de fusion.

La gestion des conflits reste souvent un endroit sombre et mystérieux: une situation où les choses sont mal brisées et où l'on ne sait pas comment en sortir (sans aggraver les choses).

S'il est vrai que les conflits de fusion sont une partie inévitable de la vie d'un développeur, l'inconfort dans ces situations est entièrement facultatif.

Mon intention avec cet article est d'apporter une certaine clarté à ce sujet: comment et quand les conflits se produisent généralement, ce qu'ils sont réellement et comment les résoudre - ou les annuler.

Lorsque vous comprenez bien ces choses, vous serez en mesure de gérer les conflits de fusion d'une manière beaucoup plus détendue et confiante. 😍

Comment et quand les conflits surviennent

Le nom le dit déjà: des "conflits de fusion" peuvent survenir lors du processus d'intégration de commits d'une autre source.

Gardez à l'esprit, cependant, que "l'intégration" ne se limite pas à la "fusion de branches". Cela peut également se produire lors du rebasage ou du rebasage interactif, lors de l'exécution d'un cherry-pick ou d'un pull, ou même lors de la réapplication d'un Stash.

Toutes ces actions effectuent une sorte d'intégration - et c'est à ce moment que des conflits de fusion peuvent survenir.

Mais bien sûr, ces actions n'entraînent pas à chaque fois un conflit de fusion (Dieu merci!). Idéalement, vous ne devriez vous retrouver dans ces situations que rarement. Mais quand exactement les conflits surviennent-ils?

En fait, les capacités de fusion de Git sont l'un de ses plus grands avantages: la fusion de branches fonctionne sans effort la plupart du temps, car Git est généralement capable de résoudre les choses par lui-même.

Mais il y a des situations où des changements contradictoires ont été apportés - et où la technologie ne peut tout simplement pas décider de ce qui est bien ou mal. Ces situations nécessitent simplement une décision d'un être humain.

Le vrai classique est quand la même ligne de code exacte a été modifiée en deux commits, sur deux branches différentes. Git n'a aucun moyen de savoir quel changement vous préférez! 🤔

Il existe d'autres situations similaires - par exemple lorsqu'un fichier a été modifié dans une branche et supprimé dans une autre - mais elles sont un peu moins courantes.

L' interface graphique du bureau Git "Tower" , par exemple, permet de visualiser ces types de situations:

Comment savoir quand un conflit est survenu

Ne vous inquiétez pas: Git vous dira très clairement quand un conflit s'est produit. 😉  

Tout d'abord, il vous informera immédiatement de la situation , par exemple lorsqu'une fusion ou un rebase échoue en raison d'un conflit:

$ git merge develop Auto-merging index.html CONFLICT (content): Merge conflict in index.html CONFLICT (modify/delete): error.html deleted in HEAD and modified in develop. Version develop of error.html left in tree. Automatic merge failed; fix conflicts and then commit the result.

Comme vous pouvez le voir dans l'exemple ci-dessus, lorsque j'ai essayé d'effectuer une fusion, j'ai créé un conflit de fusion - et Git communique le problème très clairement et rapidement:

  • Un conflit dans le fichier "index.html" s'est produit.
  • Un autre conflit dans le fichier "error.html" s'est produit.
  • Et finalement, à cause des conflits, l'opération de fusion a échoué.

Ce sont les situations où nous devons fouiller dans le code et voir ce qui doit être fait.

Dans le cas peu probable où vous auriez ignoré ces messages d'avertissement lorsque le conflit s'est produit, Git vous en informe également chaque fois que vous exécutez git status:

$ 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/rm ..." as appropriate to mark resolution) deleted by us: error.html both modified: index.html

En d'autres termes: ne vous inquiétez pas de ne pas remarquer les conflits de fusion. Git s'assure que vous ne pouvez pas les ignorer.

Comment annuler un conflit dans Git et recommencer

Les conflits de fusion viennent avec un certain air d'urgence. Et à juste titre: vous devrez vous en occuper avant de pouvoir continuer votre travail.

Mais bien que les ignorer ne soit pas une option, "gérer les conflits de fusion" ne signifie pas nécessairement que vous devez les résoudre. Les annuler est également possible!

Cela vaut peut-être la peine d'être répété: vous avez toujours la possibilité d'annuler un conflit de fusion et de revenir à l'état précédent. Cela est vrai même lorsque vous avez déjà commencé à résoudre les fichiers en conflit et que vous vous trouvez dans une impasse.

Dans ces situations, il est bon de garder à l'esprit que vous pouvez toujours recommencer et revenir à un état propre avant même que le conflit ne se produise.

À cette fin, la plupart des commandes sont livrées avec une --abortoption, par exemple git merge --abortet git rebase --abort:

$ git merge --abort $ git status On branch main nothing to commit, working tree clean

Cela devrait vous donner l'assurance que vous ne pouvez vraiment pas gâcher. Vous pouvez toujours abandonner, revenir à un état propre et recommencer.

À quoi ressemblent vraiment les conflits dans Git

Maintenant, sachant que rien ne peut briser, voyons à quoi ressemble vraiment un conflit sous le capot. Cela démystifiera ces petits voyous et, en même temps, vous aidera à perdre le respect pour eux et à prendre confiance en vous.

À titre d'exemple, regardons le contenu du fichier "index.html" (actuellement en conflit) dans un éditeur:

Git was kind enough to mark the problem area in the file, enclosing it in <<<<<<< HEAD and >>>>>>> [other/branch/name]. The content that comes after the first marker originates from our current working branch. Finally, a line with ======= characters separates the two conflicting changes.

How to Solve a Conflict in Git

Our job as developers now is to clean up these lines: after we're finished, the file has to look exactly as we want it to look.

It might be necessary to talk to the teammate who wrote the "other" changes and decide which code is actually correct. Maybe it's ours, maybe it's theirs - or maybe a mixture between the two.

This process - cleaning up the file and making sure it contains what we actually want - doesn't have to involve any magic. You can do this simply by opening your text editor or IDE and starting to making your changes.

Often, however, you'll find that this is not the most efficient way. That's when dedicated tools can save time and effort:

  • Git GUI Tools: Some of the graphical user interfaces for Git can be helpful when solving conflicts. The Tower Git GUI, for example, offers a dedicated "Conflict Wizard" that helps visualize and solve the situation:
  • Dedicated Merge Tools: For more complicated conflicts, it can be great to have a dedicated "Diff & Merge Tool" at hand. You can configure your tool of choice using the "git config" command. (Consult your tool's documentation for detailed instructions.) Then, in case of a conflict, you can invoke it by simply typing git mergetool. As an example, here's a screenshot of "Kaleidoscope" on macOS:

After cleaning up the file - either manually or in a Git GUI or Merge Tool - we have to commit this like any other change:

  • By using git add on the (previously) conflicted file, we inform Git that the conflict has been solved.
  • When all conflicts have been solved and added to the Staging Area, you need to complete the resolution by creating a regular commit.

How to Become More Confident and Productive

Many years ago, when I started using version control, merge conflicts regularly freaked me out: I was afraid that, finally, I had managed to break things for good. 😩

Only when I took the time to truly understand what was going on under the hood was I able to deal with conflicts confidently and efficiently.

The same was true, for example, when dealing with mistakes: only once I learned how to undo mistakes with Git was I able to become more confident and productive in my work.

I highly recommend taking a look at the free "First Aid Kit for Git", a collection of short videos about how to undo and recover from mistakes with Git.

Have fun becoming a better programmer!

About the Author

Tobias Günther is the CEO of Tower, the popular Git desktop client that helps more than 100,000 developers around the world to be more productive with Git.