Beaucoup de développeurs utilisent Git tous les jours avec quatre commandes: git add, git commit, git push, git pull. Ça suffit au quotidien. Puis un jour, le tech lead demande "tu peux rebase ta branche sur main avant de merger ?". Là, c'est le trou noir. Direction Google, puis dix articles qui se contredisent.
C'est une maîtrise partielle de Git: quatre commandes sur la trentaine d'utiles, et les six qui débloqueraient le plus de situations restent dans l'angle mort. Quand un truc tourne mal, la solution de secours devient "je supprime ma branche et je repars de main". Parfois une demi-journée de travail passe à la trappe, et on se dit que c'est le prix à payer.
Ces commandes ne sont pas difficiles en soi. Ce qui manque, c'est un modèle mental clair. La plupart des tutoriels donnent des recettes ("tape ça, ça marche") sans la logique en dessous. Dès que la situation s'écarte un peu de la recette, plus rien ne tient.
Cet article donne la logique derrière six commandes Git qui font peur, dans un ordre qui construit la compréhension étape par étape. À la fin, tu n'auras pas tout couvert, mais tu auras le modèle mental pour apprendre le reste seul.
Le problème : on t'a appris Git comme une liste de recettes
La plupart des cours Git suivent ce schéma : voici les commandes de base, faites-les dans cet ordre, copiez le pense-bête. Ça marche pour les premières semaines. Ça craque dès qu'une situation imprévue arrive : un commit raté à modifier, deux branches qui ont divergé, un fichier qui revient de nulle part.
Le mot qui manque dans cet apprentissage, c'est "graphe". Git n'est pas un éditeur de texte avec un bouton sauvegarder. C'est un graphe de commits, chaque commit pointant vers son ou ses parents. Toutes les commandes que tu trouves obscures sont en réalité des manipulations sur ce graphe. Une fois que tu visualises le graphe, tout devient évident.
L'autre concept-clé manquant, c'est la distinction entre les "zones" de Git : le working directory (ton dossier de travail), l'index ou staging (ce qui sera dans le prochain commit), le HEAD (le dernier commit de ta branche locale), et le remote (le serveur, GitHub ou autre). Chaque commande déplace des choses entre ces zones.
Avec ces deux idées, le graphe et les zones, 80% du mystère de Git disparaît. Les commandes ne sont plus des incantations, ce sont des verbes qui agissent sur des objets bien définis.
Le principe : six commandes dans l'ordre où elles s'apprennent
1. git stash : poser ton boulot en cours sans commit
Le cas typique : tu es en train de bosser sur une fonctionnalité, ton code n'est pas prêt à être commit, et il faut que tu changes de branche pour une urgence. Tu ne peux pas changer de branche avec des modifications non sauvées, Git va râler.
git stash met de côté tes modifications en cours dans une pile. Tu peux maintenant changer de branche, traiter ton urgence, revenir, et faire git stash pop pour récupérer ton travail.
Trois commandes te suffisent. git stash pour ranger. git stash list pour voir ce qui est rangé. git stash pop pour récupérer le dernier. C'est la commande la plus simple de la liste, et elle te sauve plusieurs fois par semaine.
2. git reset : revenir en arrière, à trois niveaux différents
La commande qui fait paniquer parce que ses options sont confuses. En vrai, c'est simple si tu te rappelles des trois zones (working directory, index, HEAD).
git reset --soft HEAD~1: annule le dernier commit, mais garde tes changements en staging. Utile quand tu as mal nommé un commit ou oublié un fichier.git reset --mixed HEAD~1(ou simplementgit reset HEAD~1) : annule le commit et sort tes changements du staging, ils restent dans tes fichiers.git reset --hard HEAD~1: annule le commit ET supprime les changements de tes fichiers. Tu perds ton travail. À utiliser seulement quand tu es absolument sûr.
Modèle mental : soft annule le commit, mixed annule le commit et le staging, hard annule tout. La dangerosité augmente avec la longueur du mot. Mémorise cette progression et tu ne fais plus jamais d'erreur.
3. git rebase : réécrire l'historique de ta branche
La commande qui terrorise les juniors et qui est en réalité super utile. Le rebase prend tes commits et les "rejoue" par-dessus une autre branche, comme si tu avais fait ton travail à partir de cette branche dès le départ.
Cas typique : tu as une branche feature/login partie de main il y a trois jours. Pendant ce temps, main a avancé. Tu veux que ta branche soit basée sur la version actuelle de main pour éviter les conflits au merge.
git checkout feature/login
git fetch origin
git rebase origin/main
Git va replacer tes commits par-dessus la version actuelle de main. S'il y a un conflit, il s'arrête, tu résous, tu fais git add sur les fichiers résolus, puis git rebase --continue.
Règle absolue : tu ne rebase JAMAIS une branche partagée avec d'autres. Le rebase réécrit l'historique, et si quelqu'un travaillait sur l'ancienne version, tu casses tout. Sur ta branche perso avant un merge dans main, c'est parfait. Sur main, jamais.
4. git cherry-pick : récupérer un commit précis sans tout merger
Tu as fait un commit important sur une branche, et tu veux ce commit aussi sur une autre branche, sans merger toute la branche d'origine. C'est exactement le cas pour cherry-pick.
git checkout main
git cherry-pick <hash-du-commit>
Tu récupères le hash du commit avec git log (les 7 premiers caractères suffisent). Tu le cherry-pick sur la branche cible, et Git applique exactement ce commit à cet endroit.
Utilisations courantes : appliquer un hotfix sur plusieurs versions, récupérer une partie d'une branche que tu ne veux pas fusionner complètement. À utiliser avec parcimonie, parce que tu duplique l'historique du commit (le même changement existe à deux endroits avec deux hashs différents).
5. git reflog : ton filet de sécurité absolu
La commande la plus importante de cette liste, et la moins connue. Git garde une trace de tous les déplacements de HEAD pendant 90 jours, même quand tu fais des opérations destructrices. Cette trace, c'est le reflog.
git reflog
Tu vois une liste de toutes les opérations récentes avec leur hash. Tu as fait un reset --hard et tu as perdu des commits ? Tu retrouves leur hash dans le reflog, et tu fais git reset --hard <hash> pour revenir à cet état. Tes commits sont récupérés.
Tant que tu connais le reflog, tu ne peux quasiment rien perdre dans Git. C'est cette commande qui devrait te donner le courage d'expérimenter avec les autres : tu sais que tu peux toujours revenir en arrière.
6. git rebase -i : réécrire proprement ses commits avant un merge
Le rebase interactif. Sur une feature branch, tu as fait dix commits : "wip", "fix typo", "ajout bouton", "encore un fix", "ah ça marche". Avant de pousser pour review, tu veux nettoyer cet historique. Le rebase interactif fait ça.
git rebase -i HEAD~5
Git ouvre ton éditeur avec la liste des 5 derniers commits. Pour chacun, tu peux : pick (garder), squash (fusionner avec le précédent), reword (changer le message), drop (supprimer). Tu sauves, Git réécrit ta branche.
Résultat : au lieu de dix commits sales, tu présentes deux commits propres en review. Le tech lead voit ta vraie intention, pas le brouillon. C'est un signe de maturité dev qui se remarque très vite.
Exemple : un workflow propre de la branche au merge
Voici comment ces commandes s'enchaînent dans un workflow réel, sur une branche de fonctionnalité.
# Je pars de main a jour
git checkout main
git pull
# Je cree ma branche
git checkout -b feature/checkout-stripe
# Je code, je commit plusieurs fois
git add .
git commit -m "wip stripe integration"
# ... 4 autres commits brouillons ...
# Avant de pousser, je nettoie mon historique
git rebase -i HEAD~5
# Je squashe les 5 commits en 2 propres
# Pendant ce temps, main a avance, je me mets a jour
git fetch origin
git rebase origin/main
# Si conflit : je resous, git add, git rebase --continue
# Je pousse (avec --force-with-lease car j'ai reecrit l'historique)
git push --force-with-lease origin feature/checkout-stripe
# J'ouvre la PR sur GitHub, elle est propre, le tech lead est content
Ce workflow combine rebase interactif (nettoyage) et rebase classique (mise à jour). À la fin, ta branche a un historique propre et linéaire, qui se mergue sans bavure dans main.
Important : --force-with-lease au lieu de --force. Cette variante refuse de pousser si quelqu'un d'autre a poussé sur ta branche entre-temps, ce qui te protège d'écraser le travail d'un collègue.
Pièges classiques à éviter
Faire git push --force sur une branche partagée
Tu as réécrit l'historique de ta branche locale, tu pousses avec --force. Tu écrases sans le savoir trois commits qu'un collègue avait poussés. Il a perdu son travail. La journée est gâchée.
Toujours --force-with-lease, jamais --force. La différence prend trois caractères en plus et te sauve des catastrophes.
Rebase main sur ta branche au lieu de l'inverse
Tu fais git checkout main puis git rebase feature/login en pensant que tu mets à jour ta branche. En réalité, tu réécris l'historique de main. Catastrophe en équipe.
La règle simple : tu te places toujours sur ta branche de feature, et tu rebase sur main. git checkout feature puis git rebase main. Tu rebase ta branche sur autre chose, pas l'inverse.
Paniquer après un git reset --hard
Tu as fait git reset --hard HEAD~3, tu réalises que tu viens de perdre tes trois derniers commits. Tu paniques, tu googles, tu te dis que c'est foutu.
Le reflog est ton ami. git reflog, tu retrouves le hash de ton état précédent, git reset --hard <hash>, tu es de retour. Ce n'est jamais foutu tant que tu n'as pas attendu 90 jours.
Mal nommer ses commits
"fix", "wip", "update", "encore un truc". Six mois plus tard, tu cherches qui a introduit un bug, l'historique ne te dit rien.
Un bon message de commit commence par un verbe à l'impératif (add, fix, refactor, remove), décrit le quoi et le pourquoi, tient en une ligne courte (50 caractères ou moins pour le titre). Si tu utilises le rebase interactif, tu nettoies les "wip" avant de pousser. C'est ce qui distingue un historique professionnel d'un historique brouillon.
Ignorer les conflits au lieu de les comprendre
Tu as un conflit lors d'un merge ou d'un rebase, tu paniques, tu acceptes "toutes les leurs" ou "toutes les miennes" sans regarder. Tu pousses du code cassé.
Un conflit n'est pas une erreur, c'est une question que Git te pose : "deux versions différentes existent pour ces lignes, laquelle veux-tu ?". Tu lis le fichier, tu choisis ligne par ligne, tu testes, tu commits. Les conflits sont normaux, c'est ta capacité à les résoudre qui te distingue.
Croire qu'il faut tout savoir avant d'utiliser
Tu attends de "vraiment comprendre Git" pour oser utiliser rebase. Tu ne comprends pas tant que tu n'utilises pas. Tu utilises seulement quand tu comprends. Tu es coincé.
Tu crées une branche jetable sur ton projet perso, tu fais des commits bidons, et tu joues. reset, rebase, cherry-pick, tu casses tout, tu récupères avec le reflog. Une heure de jeu vaut dix heures de tutoriel.
Pour aller plus loin
Maîtriser Git change ton positionnement dans l'équipe. Un junior qui sait rebase proprement passe pour un dev sérieux, parce que la propreté de son historique de commits se voit en review. L'article sur les apprendre par la pratique plutôt que par les tutoriels s'applique parfaitement ici : tu ne maîtrises Git qu'en l'utilisant sur de vrais projets.
Côté formation, la formation Git et GitHub : versionner et collaborer couvre ces commandes en profondeur avec des exercices reproductibles. La formation CI/CD avec GitHub Actions prend le relais pour la partie automatisation autour de Git.