Aller au contenu
Antoine Le LouëtDéveloppeur senior indépendant (Accueil)
← Revenir au Journal

Conseils6 min de lecture

Comprendre Git : du dessin sur papier au merge

Les branches dessinées sur papier m’aidaient à expliquer Git aux juniors. Un simulateur prolonge cette approche pour comprendre merge, rebase et reset.

Avant le merge, main pointe vers B et atelier vers C, avec A comme parent commun. Après le merge, main pointe vers M, dont les parents sont B et C. atelier reste sur C.
Un merge entre deux historiques divergents crée ici le commit M. Les traits relient chaque commit à ses parents ; les étiquettes indiquent la position des branches.

Le moment où l’on sortait une feuille

Pendant des années, j’ai appris Git à des stagiaires et à des juniors. Les premières commandes passaient, puis les mêmes questions revenaient : « Là, on est sur quelle branche ? » ou « Pourquoi mon commit a disparu ? » Expliquer un merge avec des mots finissait souvent par nous ramener au même endroit : une feuille de papier.

On dessinait des ronds pour les commits, des branches et des flèches. En regardant le dessin, on pouvait suivre ce qui changeait après une commande. La discussion devenait plus précise : quelle branche bouge ? À quel commit est-elle rattachée ? Que reste-t-il de l’autre côté ?

Cette difficulté à se représenter l’historique mérite qu’on s’y arrête. On peut utiliser Git tous les jours avec quelques commandes apprises par habitude, puis hésiter dès que les branches divergent. Pour l’expliquer, je préfère rendre visible ce que la commande transforme.

Lire les étiquettes avant de suivre les lignes

Un commit enregistre un état du projet et les liens vers ses parents. Une branche est une référence mobile vers un commit. Quand on crée une branche, on ajoute donc un nom pointant vers un commit existant. Le prochain commit fait avancer la branche sur laquelle on travaille.

HEAD indique généralement la branche courante. Il peut aussi pointer directement vers un commit : c’est le mode HEAD détachée. Sur un dessin, je commence par placer ces étiquettes. Elles permettent de comprendre pourquoi deux personnes regardant le même historique peuvent travailler à des endroits différents.

Dans la couverture de cet article, main et atelier partagent le commit A, puis chacune a reçu un nouveau commit. B et C ont donc le même parent. Cette situation suffit pour poser une question concrète : que va faire Git si l’on fusionne atelier dans main ?

Le dessin devient un terrain d’essai

Le lien partagé mène à Explain Git with D3, le projet de onlywei. Il propose des espaces de simulation par commande : on saisit une commande Git et on observe son effet sur le graphe. Les exercices couvrent notamment les commits, les branches, le merge, le rebase et le reset. Le lien direct vers l’exercice merge figure dans les sources en fin d’article.

Pour une personne qui débute, cela permet d’essayer sans toucher à son projet. Pour un mentor, le graphe fournit un support commun à l’explication. Je propose de marquer une pause avant chaque commande : demander où seront les étiquettes après son exécution, puis comparer cette prédiction au résultat affiché.

Le simulateur utilise notamment git checkout pour changer de branche. Les commandes proposées correspondent à son interface ; il ne faut pas supposer qu’il reproduit toutes les possibilités d’un terminal Git.

Ce que le merge ajoute à l’historique

Avec main sur B et atelier sur C, on se place sur main avant de lancer git merge atelier. La fusion rapproche les modifications des deux branches depuis leur ancêtre commun A. Si elle aboutit, elle crée ici un commit M avec deux parents, B et C. main avance vers M ; atelier reste sur C.

Le dessin aide aussi à comprendre le fast-forward. Si main n’avait reçu aucun commit après A, Git pourrait simplement faire avancer main jusqu’à C. Dans ce cas, avec le comportement par défaut, aucun commit de merge supplémentaire ne serait nécessaire.

Un conflit concerne le contenu à réunir. Lorsque Git ne peut pas décider comment combiner des modifications, la fusion s’arrête pour laisser résoudre ce conflit. Un graphe explique les liens entre commits ; les fichiers restent nécessaires pour choisir le résultat attendu.

Observer aussi les identifiants des commits

Pour comparer, on peut repartir de la divergence initiale et rebaser atelier sur main. Dans cet exemple simple, Git rejoue la modification de C sur B et produit un nouveau commit C′. Son parent change, son identifiant aussi. La branche atelier pointe alors vers C′. Cela explique pourquoi un rebase demande de se coordonner lorsqu’une autre personne travaille déjà à partir des commits concernés.

Avant le rebase, B et C ont A pour parent. Après le rebase d’atelier sur main, main reste sur B et atelier pointe sur C′, dont le parent est B. L’ancien C ne devient pas C′ : un nouveau commit est créé.
Les traits relient les parents. Le dessin isole le rebase simple décrit ; l’ancien C n’est plus pointé par atelier, ce qui ne signifie pas sa suppression immédiate. Les effets de reset sur les fichiers sont un autre sujet.

Avec git reset et une cible de commit, on déplace la branche courante vers cette cible. Les options déterminent aussi ce qui arrive à l’index, où l’on prépare le prochain commit, et aux fichiers de travail. --soft les conserve, --mixed remet l’index à l’état ciblé et conserve les fichiers, --hard remet les deux à cet état et peut faire perdre du travail local.

Le site ne modélise pas la préparation des fichiers avec git add et ne prend en charge que --hard pour sa simulation de reset. Cette simplification aide à observer le graphe, mais elle laisse de côté une partie essentielle du comportement réel. Un commit qui n’apparaît plus dans l’historique d’une branche n’est pas forcément effacé immédiatement : le reflog local peut aider à retrouver une ancienne position, tant que les objets correspondants existent encore.

Refaire l’expérience dans un dépôt jetable

Avec Git installé et une identité de commit configurée, voici un exercice à lancer dans un nouveau dossier. Les commits sont volontairement vides : on isole la forme de l’historique, sans prétendre tester une fusion de fichiers ou un conflit.

Terminal
mkdir git-visuel
cd git-visuel
git init -b main
git commit --allow-empty -m "A : point de départ"
git checkout -b atelier
git commit --allow-empty -m "C : travail sur atelier"
git checkout main
git commit --allow-empty -m "B : travail sur main"
git merge atelier -m "M : fusion de atelier"
git log --graph --oneline --decorate --all

Avant le merge, dessinez les positions de main et atelier. Après la commande, vérifiez que main pointe vers le commit de fusion et qu’atelier reste sur C. Pour afficher les deux identifiants parents de M, utilisez git show -s --format=%P HEAD.

Lors du prochain accompagnement, laissez la personne qui apprend tenir le crayon ou saisir les commandes. Demandez-lui de prévoir le prochain état du graphe et d’expliquer ce qu’elle observe. Vous saurez alors quel point reprendre ensemble, plutôt que d’ajouter une nouvelle commande à mémoriser.

Sources et liens utiles

Partager sur LinkedIn (nouvel onglet)

Poursuivre la lecture
Tous les articles de la catégorie →