Faites face à votre premier conflit
Un pour tous, tous pour un ! Ce dicton popularisé par les Trois Mousquetaires met en avant l’importance de la solidarité. Et c’est un credo qui correspond bien au travail collaboratif avec Git et GitHub.
Oui mais voilà, nous avons aussi les défauts de nos qualités. Git et GitHub n’y échappent pas, la collaboration peut être source de problèmes à résoudre.
Euh… tu es en train de dire que ce n’est pas une si bonne idée d’utiliser Git et GitHub ?
C’est une très bonne idée, rassurez-vous ! Simplement il faut être conscient que Git a des limites, et que nous devons apprendre à les gérer.
Je vous explique : le travail collaboratif permet à plusieurs développeurs de manipuler les fichiers du projet. Mais que se passe-t-il si 2 développeurs modifient la même ligne d’un fichier ? Comment Git choisit-il la modification à retenir ?
La réponse est simple : Git ne choisit pas. Et c’est justement sa limite ! Il considère que ce n’est pas sa responsabilité, alors il va vous demander de faire ce choix vous-même. Comment ? En créant un conflit !
Pour comprendre, arrêtons-nous sur le scénario suivant :
En bon contributeur, vous modifiez la ligne 14 du fichier README.md pour indiquer les prérequis (voir l’issue 3).
Puis vous pushez votre mise à jour sur le repository GitHub distant. Le push est refusé car vous n’êtes plus à jour avec ce repository GitHub distant. En effet, d’autres commits ont été réalisés depuis votre dernière synchronisation.
Pour mettre à jour votre projet, vous exécutez la commande git pull. Cette dernière va récupérer les derniers commits puis faire un merge avec votre copie locale.
Et paf, un conflit apparaît ! (Et non pas un Pokémon, oui oui je vous ai vu venir. )
En effet, la ligne 14 du même fichier README.md a été modifiée par un de vos collaborateurs. Git ne sait plus quoi faire car il ne peut pas deviner quelle est la bonne ligne entre les 2. Doit-il conserver la version de votre collaborateur ou la vôtre ?
Résultat, à nous d’apprendre à résoudre les conflits car tant que le conflit existe, nous ne pourrons pas pusher notre code.
D’autre part, comme vous l’avez peut-être noté dans ce scénario, c'est l’opération de merge qui a déclenché le conflit. Vous pouvez donc déduire qu’un merge entre 2 branches peut également créer des conflits.
Savoir résoudre un conflit : voilà ce que je vais vous apprendre dans la suite du chapitre ! Commençons par comprendre les conflits grâce à la commande git status.
Pour simuler ce conflit sur votre poste de travail, suivez les étapes suivantes :
git pull ;
modifier en local le fichier README.md ;
git add README.md ;
git commit -m “#3 Ajout d’un prérequis" ;
modifier via l’interface web de GitHub le fichier README.md (avec un texte différent de la modification locale) ;
git push ;
git pull.
Analysez le conflit grâce à git status
Les développeurs apprennent très rapidement qu’il ne faut pas avancer tête baissée dans un problème sans prendre le temps de comprendre précisément ce qu’il se passe. Et cette situation n’échappe pas à la règle ! Nous allons devoir investiguer !
Pour comprendre précisément un conflit, arrêtons-nous sur la description de ce dernier pour commencer. Dans notre scénario, c’est au moment de l’appel de git pull que le conflit est apparu. Voilà le type de visuel que vous pouvez avoir dans ce cas :
$ git pull remote: Enumerating objects: 5, done. remote: Counting objects: 100% (5/5), done. remote: Compressing objects: 100% (3/3), done. remote: Total 3 (delta 2), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (3/3), 718 bytes | 79.00 KiB/s, done. From https://github.com/romainsessa/7688581-Expert-Git-GitHub 1425593..a6c82f7 main -> origin/main Auto-merging README.md CONFLICT (content): Merge conflict in README.md Automatic merge failed; fix conflicts and then commit the result.
Les 3 dernières lignes sont très claires : le merge du fichier README.md a échoué, et un “Merge conflict” a été créé.
Pour en savoir plus sur ce problème, utilisons la commande git status.
Voici le résultat de la commande git status juste après l’appel du git pull précédemment montré :
$ git status On branch main Your branch and 'origin/main' have diverged, and have 1 and 1 different commits each, respectively. (use "git pull" to merge the remote branch into yours) 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: README.md no changes added to commit (use "git add" and/or "git commit -a")
La phrase “You have unmerged paths.” signifie qu’une opération de merge n’a pas pu aboutir. Git nous propose ensuite 2 solutions :
(fix conflicts and run “git commit”) : résoudre le conflit.
(use “git merge –abort to abort the merge) : annuler le merge, ce qui retire le conflit mais ne nous permet pas pour autant de pusher notre fichier README.md.
Si nous choisissons la solution 1), alors la suite nous intéresse particulièrement car cela nous indique le ou les fichiers à corriger.
(use “git add <file>...” to mark resolution) both modified: README.md
Ce texte nous informe que le fichier README.md a été modifié par 2 personnes. Suite à cela, sachez que Git a modifié le fichier pour y écrire le détail du conflit.
Nous avons recueilli suffisamment d'informations sur le conflit pour aller de l’avant, il est temps de le résoudre !
Résolvez votre conflit
Rappelons avant tout que résoudre un conflit signifie prendre une décision. Dans notre cas, quelle version de la ligne 14 dois-je conserver ? La version qui vient du dépôt distant ? Celle qui a été écrite en local ? Ou bien une version hybride entre les 2 ?
En résumé, nous avons 3 possibilités :
Conserver la version locale aux dépens de la version distante.
Conserver la version distante aux dépens de la version locale.
Modifier le fichier en conflit et en faire une 3e version qui sera ensuite conservée.
Mais comment choisir ?
Il n’existe aucune réponse absolue à cette question ! Tout dépend de la situation dans laquelle vous vous trouvez. Cela vous demandera peut-être d’échanger au préalable avec le collaborateur qui a travaillé sur le même fichier que vous.
Ceci dit, il vous sera certainement utile de comprendre le conflit au sein du fichier pour prendre une décision.
Je vous propose donc d’ouvrir le contenu du fichier, je vous montre uniquement la section Prérequis :
### Prérequis Pour exécuter en local le projet Open Transport, vous devez au préalable installer : ``` <<<<<<< HEAD Un navigateur web ======= Un serveur web comme XAMPP A définir >>>>>>> a6c82f75db73fc5aaec7fc2ef175253133876565 ```
Décryptons :
Les chaînes de caractères <<<<<<< et >>>>>>> balisent la zone de conflit ;
La première partie du texte qui suit le mot HEAD correspond à la modification locale ;
La chaîne ======= indique la fin de cette modification, et il s’ensuit la modification distante en conflit ;
Le texte a6c82f75db73fc5aaec7fc2ef175253133876565 correspond au numéro d’identification unique du commit d’où provient le texte en conflit.
Nous devons donc désormais choisir entre :
conserver le texte : Un navigateur web ;
conserver le texte : Un serveur web comme XAMPP A définir ;
faire une troisième version qui pourrait être un mix des deux premières options.
Très bien, nous y voyons clair et nous sommes en mesure de prendre une décision !
Maintenant, l’important est que vous sachiez techniquement quelles commandes utiliser pour chacune de ses situations. C’est ce que nous allons voir maintenant !
Utilisez la commande Git adaptée
Quelles commandes utiliser pour chaque possibilité présentée dans la section précédente ? Laissez-moi vous montrer dans la démonstration qui suit :
Récapitulons ensemble :
Premièrement, pour conserver la version distante, j’ai utilisé la commande : git checkout --theirs README.md.
Deuxièmement, pour conserver la version locale, j’ai utilisé la commande : git checkout --ours README.md.
Et enfin troisièmement, pour corriger le conflit manuellement, j’ai ouvert le fichier et modifié son contenu. Cette modification implique d’enlever les lignes ajoutées automatiquement par Git, et de conserver le texte de mon choix.
Pour chacune des situations, j’ai ensuite eu besoin d'exécuter les commandes git add, git commit et git push (commandes dont vous êtes familier !).
À vous de jouer !
Alors que vous travaillez sur l’issue n° 4, vous faites face à un nouveau conflit !
Créez un conflit
Tout comme pour l’exemple développé dans ce chapitre, commencez par créer le conflit. Pour cela, suivez les étapes suivantes :
git pull ;
modifier en local le fichier CONTRIBUTING.md pour corriger la faute ;
git add CONTRIBUTING.md ;
git commit -m “#4 Correction d’une faute de frappe” ;
modifier via l’interface web de GitHub le fichier CONTRIBUTING.md (avec un texte différent de la modification locale) ;
git push ;
git pull.
Résolvez le conflit
Résolvez ensuite le conflit avec chacune des méthodes expliquées précédemment.
Une fois le conflit résolu avec l’une des méthodes, vous devrez recréer le conflit pour le résoudre avec une autre méthode.
Vous avez réussi ? Super !
Vous avez eu quelques difficultés ? Aucun problème, retrouvez-moi dans la vidéo suivante pour que je vous montre comment faire.
En résumé
Git crée un conflit lorsqu’il ne sait pas quelle version d’un fichier il doit conserver. Cela arrive quand un fichier a été modifié au même endroit par 2 sources distinctes !
git status permet de comprendre la nature du conflit : c’est votre point de départ pour le résoudre.
À vous de choisir la solution qui vous convient le mieux pour résoudre votre conflit :
conserver la version distante ;
conserver la version locale ;
faire une version adaptée à la circonstance.
Vous voilà capable de résoudre un conflit avec succès !
Dans le prochain chapitre, vous apprendrez à soigner l’historique du projet de manière à faciliter la gestion de votre code.