Anaïs Sparesotto
Git · AvancéIntermédiaire≈ 2h30 · 8 chapitres

Git : passer au niveau supérieur

Rebase, cherry-pick, reflog, hooks, signatures, worktrees, bisect. Tout ce que tu utiliseras quand tu sortiras du cycle add/commit/push de base.

À la fin du cours, tu sais

  • Choisir un workflow adapté à ton équipe (Git Flow, GitHub Flow, trunk-based)
  • Maîtriser rebase, interactive rebase et cherry-pick
  • Récupérer un commit perdu avec reflog
  • Versionner proprement avec tags et bisect une régression
  • Mettre en place des hooks pour la qualité locale
  • Signer tes commits et utiliser les worktrees

Prérequis

  • Avoir suivi le cours « Premiers pas avec Git et GitHub » ou équivalent
  • Être à l'aise avec branch, merge, push, pull, pull requests

Chapitre 1

Stratégies de branches et workflows

Choisir le bon modèle de collaboration, c'est la décision qui structure tout le reste. Trois grandes familles dominent.

Les 3 workflows principaux

  • Git Flow : main, develop, release/*, hotfix/*, feature/*. Adapté aux releases versionnées (mobile, desktop, banking)
  • GitHub Flow : une seule branche longue main, feature branches courtes, déploiement continu
  • Trunk-Based Development : tout le monde commit fréquemment sur main, feature flags pour le code en cours, release every commit

Critères de choix

  • Taille de l'équipe
  • Fréquence des déploiements (par jour ? par mois ?)
  • Contraintes réglementaires (banking, santé : Git Flow souvent imposé)
  • Maturité de la CI/CD (le trunk-based exige une CI solide)

Conventions de nommage

git switch -c feat/auth-oauth          # nouvelle fonctionnalité
git switch -c fix/null-on-signup       # correction de bug
git switch -c chore/upgrade-deps       # tâche annexe (upgrade, doc)
git switch -c hotfix/payment-broken    # correction critique de prod
git switch -c refactor/extract-auth    # refactor sans changement de comportement

En 2025, le plus courant : GitHub Flow

Pour une équipe web qui déploie plusieurs fois par jour, GitHub Flow est presque toujours le bon choix. Simple, compatible avec PR + CI + déploiement automatique sur main. Si tu hésites, commence par lui.

Chapitre 2

Rebase vs Merge

Comprendre quand réécrire l'historique et quand le préserver. C'est le sujet qui sépare les utilisateurs basiques de Git des autres.

Merge : préserver l'historique

git merge garde l'historique réel : les deux branches restent visibles, un commit de merge matérialise leur réunion. Honnête, lisible si l'équipe est petite.

Rebase : linéariser l'historique

git rebase rejoue tes commits au sommet de la branche cible. Le résultat est un historique linéaire, comme si tu avais codé après l'autre. Plus propre à lire, mais réécrit l'histoire.

# Récupérer les derniers changements de main et rebaser ma feature dessus
git fetch origin
git rebase origin/main

# En cas de conflit
# 1) Résoudre les conflits dans les fichiers
git add fichier-resolu.ts
git rebase --continue

# Pour abandonner et revenir à l'état initial
git rebase --abort

La règle d'or du rebase

Ne rebase jamais une branche partagée publiquement. Si tu rebases main alors que tes collègues sont basés dessus, leurs commits divergent et c'est l'enfer. Rebase tes branches feature avant le merge, jamais après push partagé.

Squash and merge sur GitHub

Le bouton Squash and merge sur GitHub combine les deux : il squashe tous tes commits de feature en un seul, puis le merge sur main. Historique main propre (un commit par PR), pas besoin de rebase manuel.

Chapitre 3

Interactive rebase : nettoyer son historique

Avant de proposer une PR, on peut nettoyer ses commits pour que la review soit lisible. C'est ce que fait l'interactive rebase.

Lancer un rebase interactif

# Sur les 5 derniers commits
git rebase -i HEAD~5

# Ou jusqu'à la branche main
git rebase -i main

Git ouvre un éditeur avec la liste des commits, et tu peux changer la commande devant chacun :

  • pick : garder le commit tel quel
  • reword : modifier le message (le contenu reste)
  • squash (ou s) : fusionner avec le commit précédent, garder les messages
  • fixup (ou f) : fusionner avec le précédent, jeter le message (le plus courant)
  • drop (ou d) : supprimer le commit
  • edit : s'arrêter sur le commit pour le modifier

Le combo magique : --fixup + --autosquash

# Tu fais ton commit normal
git commit -m "feat: ajout du formulaire de login"

# Tu vois un typo plus tard, tu corriges et tu fais un fixup
git add .
git commit --fixup=<sha-du-commit-cible>

# Ton historique : ...[feat: login]...[fixup! feat: login]...
# Lance interactive rebase avec --autosquash
git rebase -i --autosquash main

# Git positionne automatiquement le fixup au bon endroit. Tu valides.

Push après rebase

Tu as réécrit l'historique : un git push classique sera refusé. Utilise git push --force-with-lease (pas --force). --force-with-lease refuse de pousser si quelqu'un a poussé entre-temps, protégeant le travail des autres.

Chapitre 4

Cherry-pick, stash, reflog

Trois outils pour manipuler des commits, mettre du travail de côté, ou récupérer un commit qu'on croyait perdu.

Cherry-pick : appliquer un commit ailleurs

# Récupérer un commit précis d'une autre branche
git cherry-pick abc1234

# Avec une référence au commit original dans le message (recommandé)
git cherry-pick -x abc1234

# Cherry-pick d'une plage de commits
git cherry-pick abc1234..def5678

Cas typique : tu as fait un hotfix sur main, tu veux l'appliquer aussi sur une branche release en cours.

Stash : mettre du travail de côté

# Tu as des modifs non commitées et tu dois changer de branche d'urgence
git stash push -m "wip: refacto navigation"

# Plus tard, retour à ton travail
git stash list                 # voir tous les stashes
git stash pop                  # appliquer le plus récent et le supprimer du stash
git stash apply stash@{1}      # appliquer un stash précis sans le supprimer
git stash drop stash@{1}       # supprimer un stash

# Inclure les fichiers non suivis (untracked)
git stash push -u -m "wip avec nouveaux fichiers"

Reflog : ton filet de sécurité

git reflog est le journal de toutes les positions de HEAD. Même un git reset --hard ne supprime pas vraiment tes commits : ils restent retrouvables via reflog pendant ~30 jours.

# Voir tous les déplacements de HEAD
git reflog

# Output exemple :
# abc1234 HEAD@{0}: reset: moving to HEAD~3
# def5678 HEAD@{1}: commit: feat: ajout du dashboard
# ...

# Récupérer un commit "perdu"
git reset --hard HEAD@{1}      # revient à la position d'avant le reset

# Ou créer une branche à partir de ce commit
git switch -c recup HEAD@{1}

Tant que tu n'as pas fait git gc

Le reflog conserve les commits perdus pendant 30 jours par défaut. Avant ce délai, rien n'est jamais vraiment perdu. À retenir : quand tu paniques, lance git reflog.

Chapitre 5

Tags, releases, bisect

Versionner proprement et savoir traquer une régression à coup sûr.

Tags annotés vs légers

  • Tag léger : juste un nom qui pointe sur un commit. git tag v1.0.0
  • Tag annoté : avec auteur, date, message. Recommandé pour les releases. git tag -a v1.0.0 -m "release initiale"
# Créer un tag annoté
git tag -a v1.4.0 -m "release auth oauth"

# Pousser les tags (pas inclus dans un push classique)
git push origin v1.4.0
git push origin --tags    # tous les tags

# Décrire un commit par rapport au dernier tag
git describe              # "v1.4.0-12-gabc1234"
                          # = 12 commits après v1.4.0, sha=abc1234

SemVer

Convention MAJOR.MINOR.PATCH : MAJOR pour breaking change, MINOR pour ajout compatible, PATCH pour bug fix. Outils comme semantic-release ou changesets automatisent les releases à partir des Conventional Commits.

Bisect : recherche dichotomique du commit fautif

Une régression apparaît, mais entre quel commit ? git bisect fait une recherche dichotomique : tu marques un commit qui marchait et un qui casse, Git te propose le milieu, tu testes, tu réponds good ou bad, et il converge.

git bisect start
git bisect bad                     # le commit actuel a un bug
git bisect good v1.3.0             # à v1.3.0 ça marchait

# Git checkout un commit au milieu
# Tu testes ton app
# Puis tu réponds :
git bisect bad                     # ou good selon le résultat

# Quand tu trouves : Git affiche le commit fautif
git bisect reset                   # revenir à la position de départ
Bisect automatisé avec un script de test
git bisect start HEAD v1.3.0
git bisect run npm test
# Git enchaîne automatiquement les checkouts et les tests
# jusqu'à trouver le commit qui casse les tests

Chapitre 6

Hooks, aliases et config avancée

Industrialiser ta qualité locale et raccourcir tes commandes.

Hooks client

  • pre-commit : lance avant la création du commit (lint, tests rapides)
  • commit-msg : valide le format du message (Conventional Commits)
  • pre-push : avant un push (tests complets, vérifications)

En pratique, on ne touche pas .git/hooks/ à la main. On utilise des outils : Husky (Node), lefthook (multi-langage), pre-commit (Python). Ces outils versionnent les hooks dans le repo et les installent à npm install.

Exemple avec Husky + lint-staged
// package.json
{
  "scripts": {
    "prepare": "husky"
  },
  "lint-staged": {
    "*.{ts,tsx}": ["eslint --fix", "prettier --write"]
  }
}

// .husky/pre-commit
npx lint-staged

Aliases Git utiles

git config --global alias.co "checkout"
git config --global alias.sw "switch"
git config --global alias.br "branch"
git config --global alias.lg "log --oneline --graph --all --decorate"
git config --global alias.unstage "reset HEAD --"
git config --global alias.last "log -1 HEAD"
git config --global alias.amend "commit --amend --no-edit"

Configs à mettre en place

# Pull rebase par défaut (historique linéaire)
git config --global pull.rebase true

# Mémoriser la résolution de conflits
git config --global rerere.enabled true

# Push uniquement la branche courante
git config --global push.default current

# Couleur partout
git config --global color.ui auto

Chapitre 7

Signatures et sécurité

Prouver que c'est bien toi qui a écrit ce commit. Important pour l'open source et pour les équipes qui imposent des branches protégées.

Signature SSH (Git 2.34+, le plus simple)

Tu réutilises la clé SSH que tu as déjà pour GitHub. Pas de GPG à installer.

git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true

# Signer un commit
git commit -S -m "feat: secure login"

# Vérifier
git log --show-signature

Pour que GitHub affiche le badge Verified, ajoute ta clé SSH comme Signing key dans Settings → SSH and GPG keys → New SSH key (en mode Signing key, pas Authentication key).

Signature GPG (historique)

Méthode plus ancienne, mais toujours valide. Demande d'installer GPG, de générer une clé GPG, et de l'uploader sur GitHub. Plus de friction, mais standard de l'open source historique.

Branche protégée + signature obligatoire

Sur GitHub, dans Settings → Branches → Protection rules, tu peux exiger que tous les commits sur main soient signés. Combiné avec Require pull request review, tu obtiens un haut niveau de garantie sur ce qui est mergé.

Chapitre 8

Worktrees : plusieurs branches en parallèle

Tu codes une grosse feature, et tu dois faire un hotfix urgent. Avant : tu stashes, tu changes de branche, tu codes, tu reviens, tu unstash. Avec les worktrees : tu ouvres un 2e dossier en parallèle.

Le concept

Un worktree est un dossier supplémentaire qui partage le même .git. Tu peux avoir 2 versions du repo en parallèle, sur 2 branches différentes, sans cloner deux fois ni stasher.

# Tu es dans ~/projets/mon-app sur la branche feat/dashboard
# Hotfix urgent demandé sur main

# Crée un nouveau worktree pour le hotfix
git worktree add ../mon-app-hotfix hotfix/payment-broken

# Bascule dans le dossier
cd ../mon-app-hotfix

# Tu codes, tu commits, tu pushes
git add . && git commit -m "fix: payment provider URL"
git push -u origin hotfix/payment-broken

# Une fois le hotfix mergé : supprimer le worktree
cd ../mon-app
git worktree remove ../mon-app-hotfix

# Lister les worktrees
git worktree list

# Nettoyer les worktrees obsolètes
git worktree prune

Une branche, un seul worktree

Une même branche ne peut être checkout que dans un seul worktree à la fois. Si tu essaies, Git refuse pour éviter les conflits. Logique.

Les worktrees servent aussi à tester un bug rapporté sur une vieille version sans toucher à ton travail courant. Tu sors un worktree sur le tag v1.2.0, tu reproduis, tu fermes.

🛠️ Exercice optionnel

Nettoyer une feature branch avant le merge

Tu as une branche feat/profile avec 6 commits, dont 2 typos, 1 « wip » et 1 « fix lint ». Avant d'ouvrir la PR, tu vas nettoyer l'historique pour que la review soit lisible.

Ta mission

  1. Crée la branche et fabrique l'historique pourri :
    git switch -c feat/profile main
    # 6 commits avec des messages comme :
    # - feat: ajout du composant Profile
    # - wip
    # - fix tipo
    # - feat: ajout des actions
    # - fix lint
    # - typo final
  2. Lance git rebase -i main.
  3. Marque comme fixup les commits "wip", "fix lint" et les typos.
  4. reword les 2 commits restants au format Conventional Commits.
  5. Vérifie avec git log --oneline : tu dois avoir exactement 2 commits propres.
  6. Push avec git push -u origin feat/profile --force-with-lease.
  7. Ouvre la PR sur GitHub.

Tu bloques ? Des indices, à dévoiler quand tu en as besoin.

Indice 1

Indice masqué.

Indice 2

Indice masqué.

Indice 3

Indice masqué.

✅ QCM de fin de cours

Teste tes acquis

10 questions, plusieurs réponses parfois possibles. Coche tout ce qui te semble juste, puis valide pour voir ton score et les explications.

  1. 1

    Quelle commande te permet de récupérer un commit supprimé par un git reset --hard ?

  2. 2

    Que fait git rebase -i --autosquash ?

  3. 3

    Quelle stratégie de branches convient le mieux au déploiement continu ?

  4. 4

    À quoi sert git push --force-with-lease plutôt que --force ?

  5. 5

    Quelle est la différence entre un tag annoté et un tag léger ?

  6. 6

    Que fait git cherry-pick -x abc1234 ?

  7. 7

    Quel hook Git valide le format du message de commit ?

  8. 8

    Combien de worktrees peuvent avoir la même branche en checkout simultanément ?

  9. 9

    Quelle config évite les merges parasites lors d'un git pull ?

  10. 10

    Que fait git bisect run ./test.sh ?

Tu peux laisser des questions sans réponse, elles compteront comme fausses.

Tu veux ce cours pour ton équipe ?

Je peux adapter et animer ce cours pour tes formateur·ices ou tes apprenant·es, en présentiel ou en distanciel. Parlons-en pendant l'audit gratuit.

Réserver un audit gratuit →