11. Utilisation de Git (avancé)#

Git est bien plus qu’un simple outil de versionnement. Il vous permet aussi de naviguer dans l’historique de votre projet, de revenir à une version antérieure, d’explorer l’origine d’un bug ou encore d’expérimenter en toute sécurité sur des branches parallèles. Grâce à ses commandes, vous pouvez isoler des fonctionnalités, fusionner ou réorganiser vos travaux, et même annuler proprement des modifications, que vous travailliez seul ou en équipe. Dans ce module, nous allons découvrir comment tirer parti de ces possibilités : explorer les commits passés, manipuler les branches, comprendre les fusions (merge et rebase), se déplacer dans l’arbre des versions avec des références relatives, et annuler des changements avec précision. Comprendre ces déplacements dans l’historique de Git vous donnera une grande liberté et une meilleure compréhension de l’évolution de votre code.

Voyager dans le temps avec Git

Avec Git, remonter dans le temps pour explorer des versions précédentes de votre projet est à la fois simple et puissant. Que ce soit via l’interface de votre éditeur (comme la section Commits de VS Code) ou en ligne de commande avec git log, chaque commit est identifié par un hash unique, une sorte d’empreinte numérique. Pour revenir à un état antérieur du code, il suffit d’utiliser la commande git checkout <hash_du_commit>.

Avant d’effectuer ce saut dans le passé, assurez-vous d’avoir enregistré vos modifications. Si vous avez déjà fait un git add mais ne souhaitez pas encore faire de commit, vous pouvez temporairement mettre vos changements de côté avec la commande git stash.

Voyager à travers l’historique permet notamment d’identifier le moment exact où un bug est apparu. Lorsqu’un problème survient et que vous ne parvenez pas à en cerner rapidement la cause, revenir à la dernière version stable peut être une solution précieuse.

Plus vos commits sont petits, fréquents et accompagnés de messages clairs, plus il sera facile de localiser l’introduction d’un bug. Une bonne hygiène de versionnage permet souvent d’éviter des retours en arrière trop brutaux, voire de contourner complètement le besoin d’un revert. D’ailleurs, Git ne se limite pas à des déplacements linéaires dans l’historique : il offre une grande souplesse pour naviguer, expérimenter et restructurer votre travail.

Branches et fusion dans Git

Que vous travailliez en solo ou en équipe, la branche principale de votre projet — souvent appelée main ou master — représente la version de référence de votre code.

Lorsque vous développez de nouvelles fonctionnalités ou corrigez des bugs, il est courant de créer des branches spécifiques.

Les préfixes les plus courants que vous verrez dans les noms de branches sont :

  • feat/ ou feature/ : indique que vous ajoutez une nouvelle fonctionnalité.
    Exemple : feature/hyperparametrage ou feature/previsions
  • fix/ ou bugfix/ : implique que vous ne prévoyez pas d'ajouter de nouvelles fonctionnalités, mais que vous corrigez un problème dans une fonctionnalité existante.
    Exemple : bugfix/erreur-pretraitement ou fix/modele-churn

Les branches dans Git sont extrêmement légères : ce ne sont que des pointeurs vers un commit donné. Cela signifie qu’il n’y a pratiquement aucun coût en termes de mémoire ou de performance à en créer, ce qui encourage la bonne pratique : branchez tôt, branchez souvent.

Travailler avec plusieurs branches vous permet d’isoler des modifications, de tester sans risquer de casser la version principale, et de collaborer plus efficacement. Une branche représente l’intention d’inclure un ensemble de commits, à partir d’un point précis de l’historique.

Nous allons voir comment ces branches interagissent entre elles lors des opérations de fusion (merge) ou de réécriture de l’historique (rebase). La gestion des branches est l’un des aspects les plus puissants mais aussi les plus délicats de Git. Bien la comprendre, c’est poser les bases d’un flux de travail solide et maîtrisé.

Mettre temporairement de côté des changements

git stash    # met de côté les modifications en cours sans les ajouter à l’historique
git stash pop  # restaure les modifications précédemment mises de côté
  

Fusionner des branches : merge et rebase

Maintenant que vous maîtrisez les commits et la création de branches, il est temps d’apprendre à combiner le travail effectué sur différentes branches. C’est une étape clé dans tout flux de développement : elle permet par exemple de créer une branche pour une nouvelle fonctionnalité, y développer indépendamment, puis intégrer ces changements à la branche principale (main ou master).

La première méthode pour fusionner deux branches est git merge. Cette commande crée un commit de fusion spécial, qui possède deux parents. Cela signifie : « Je souhaite intégrer le contenu de ces deux branches et de leurs historiques respectifs ». C’est une façon simple et claire d’unifier deux lignes de développement, tout en conservant leur historique parallèle.

Une autre approche, plus avancée, est la commande git rebase. Contrairement à merge, rebase rejoue les commits d’une branche en les recopiant à la suite d’une autre. L’objectif est d’obtenir un historique linéaire, comme si les développements avaient été faits l’un après l’autre, plutôt qu’en parallèle. Cette méthode rend les journaux de commits (git log) beaucoup plus lisibles et compacts.

Prenons un exemple : vous êtes sur la branche bugfix et vous souhaitez appliquer son contenu sur la branche main. Avec git rebase main, vous "déplacez" les commits de bugfix à la suite des derniers commits de main. Cela donne l’impression que tout a été développé dans un seul fil conducteur, même si ce n’est pas le cas.

Chacune de ces méthodes a ses avantages, et le choix entre merge et rebase dépend de votre flux de travail, de votre équipe, et du besoin de clarté dans l’historique du projet.

Conflits de merge (Merge Conflicts)

Un conflit de merge survient lorsque deux branches ont modifié exactement les mêmes lignes dans un même fichier. Git ne peut pas déterminer automatiquement quelle version conserver.

Pourquoi les conflits se produisent-ils ?

  • Deux développeurs modifient la même partie d'un fichier
  • Un développeur supprime un fichier tandis qu'un autre le modifie
  • Deux branches réorganisent différemment la même structure de code

Résolution des conflits

Il n'existe pas de méthode automatique pour résoudre ces conflits. Vous devez les résoudre manuellement :

<<<<<<< HEAD
Code de votre branche actuelle
=======
Code de la branche que vous essayez de fusionner
>>>>>>> nom-de-branche
  

Vous devez éditer le fichier pour choisir la version à conserver :

  • Garder l'une des versions
  • Combiner les deux versions
  • Écrire quelque chose de complètement différent

Une fois les modifications effectuées, vous marquez le conflit comme résolu :

git add fichier-avec-conflit.txt
git commit -m "Résolution des conflits entre la branche feature/login et master"
  

Bonnes pratiques :

  • Si le conflit implique des modifications de deux développeurs différents, il peut être utile d'organiser un appel pour trouver ensemble la meilleure solution
  • Utilisez des outils de résolution de conflits (comme ceux intégrés dans VS Code)
  • Intégrez régulièrement les changements de la branche principale dans vos branches de fonctionnalités pour minimiser les conflits

Naviguer dans l’arbre des commits Git

Avant d’explorer des fonctionnalités avancées de Git, il est important de comprendre comment se déplacer dans l’historique des commits – souvent appelé arbre Git. Une bonne maîtrise de cette navigation rendra l’utilisation des autres commandes bien plus intuitive et efficace.

Le rôle de HEAD

Un concept central dans Git est HEAD. Il s’agit d’un pointeur symbolique qui désigne le commit actuel – autrement dit, le point de départ de toutes vos actions. En général, HEAD pointe vers le dernier commit d’une branche (par exemple, bugFix).

Chaque fois que vous effectuez un commit, Git enregistre les modifications, met à jour la branche active et avance automatiquement HEAD vers ce nouveau commit. C’est pourquoi HEAD est au cœur de nombreuses commandes Git comme commit, merge ou rebase.

Utiliser les identifiants de commits

Dans la pratique, vous n’aurez pas toujours un graphique visuel de l’historique à portée de main. Pour explorer les commits, il faudra souvent utiliser git log, qui vous fournit les identifiants uniques (hashes) de chaque commit. Ces identifiants peuvent être longs et difficiles à mémoriser — par exemple :


fed2da64c0efc5293610bdd892f82a58e8cbc5d8
  

Heureusement, Git permet d’utiliser les premiers caractères d’un identifiant, tant qu’ils restent uniques. Ainsi, fed2 suffit généralement pour désigner ce commit.

Références relatives : une navigation simplifiée

Plutôt que de manipuler des identifiants complexes, Git offre une syntaxe plus simple et intuitive : les références relatives.

Elles permettent de partir d’un point de référence connu (comme HEAD ou main) et de remonter l’historique avec des opérateurs :

L’opérateur ^
L’accent circonflexe (^) permet de remonter d’un parent. Par exemple :
main^ désigne le parent immédiat du dernier commit sur la branche main.
main^^ pointe vers le grand-parent (deux générations en arrière).

git checkout main^
  

L’opérateur ~
Le tilde (~) permet de remonter plusieurs commits d’un coup :
HEAD~4 signifie « 4 commits en arrière à partir de HEAD ».

git checkout HEAD~4
  

Les références relatives sont également utiles pour réorganiser les branches. Avec l’option -f, vous pouvez forcer une branche à pointer vers un autre commit :

git branch -f main HEAD~3
  

Cette commande replace la branche main trois commits avant HEAD. C’est un outil puissant pour corriger l’historique ou repositionner des branches lors de manipulations avancées.

Annuler des changements avec Git

Dans Git, il existe plusieurs façons d’annuler un commit, mais la méthode utilisée en pratique — notamment sur les branches partagées — est git revert, car elle respecte l’historique du projet.

git revert : annuler un commit proprement

git revert HEAD
  

Cette commande génère un commit qui inverse les changements introduits par le dernier commit (HEAD).

Et git reset ?

Il est bon de savoir qu’il existe aussi la commande git reset, qui permet de déplacer une branche vers un commit antérieur, supprimant ainsi des commits de l’historique. Cela fonctionne bien en local, mais ne doit pas être utilisé sur des branches partagées, car cela modifie l’historique de manière destructrice.

Gestion des versions avec les Tags Git

Les tags Git constituent un mécanisme pour identifier et marquer les étapes importantes d'un projet. Contrairement aux commits qui sont destinés au développement, les tags peuvent être utilisés pour signaler les versions stables pour la production.

Un tag Git fonctionne comme une étiquette permanente attachée à un commit spécifique, permettant de retrouver facilement des versions importantes sans mémoriser des identifiants de commit. Le versionnage sémantique (v1.0.0, v1.2.3) s'impose comme standard pour structurer les releases de manière cohérente et prévisible.

git tag <nom-tag>        # Créer un tag sur le commit actuel
git checkout <nom-tag>   # Revenir à une version taguée
git tag v1.0.0               # Exemple avec versionnage sémantique
  

Trois approches se distinguent : les tags de version (v1.0.0) pour marquer des releases spécifiques, le tag "stable" pour identifier la dernière version fiable, et le tag "latest" pointant vers la version la plus récente. Cette flexibilité permet d'adapter le système de versionnage aux besoins spécifiques de chaque projet tout en maintenant une communication claire sur l'état des versions disponibles.

Pour aller plus loin

Je recommande vivement d’explorer cet outil interactif pour visualiser et expérimenter les concepts abordés ici. Il permet de manipuler HEAD, les références relatives (^, ~), et les branches dans un environnement visuel, ce qui facilite grandement la compréhension de Git.

Bonnes pratiques Git
1 modification = 1 commit
Essayez de garder vos commits petits, ciblés et cohérents. Ce n’est pas une règle absolue, mais suivre le principe “commitez tôt, commitez souvent” facilite la relecture, les tests et les retours en arrière.

Pour aller plus loin
Ce guide n’a pas pour objectif d’offrir une formation exhaustive sur Git.
Il se concentre volontairement sur les bases et les étapes clés d’un workflow Git courant.
Git est un outil puissant, avec de nombreuses fonctionnalités avancées que nous n’avons pas abordées ici.

  • 🔍 Visualiser et expérimenter Git – Visualizing Git
  • Learn Git Branching (version française)
  • GitHub – Git Cheat Sheet (PDF)
  • GitLab – Git Cheat Sheet (PDF)