L’embouteillage du checkout unique
Je développe une app de barre de menu sur macOS. J’ai trois features dans le backlog: un sparkline de consommation, des notifications natives, et un widget de bureau. Les trois sont indépendantes. Les trois, je vais les faire avec Claude Code.
Le problème: Claude Code bosse dans un répertoire. Un répertoire a une branche. Et git checkout c’est comme un rond-point à une voie: y’en a qu’un qui passe.
Si je veux avancer les trois à la fois, mes options classiques sont:
Ping-pong de stash:
git stash, changer de branche, bosser,git stash pop, prier pour qu’il y ait pas de conflits. Répéter jusqu’à la folie ou la retraite, selon ce qui arrive en premier.Cloner le repo trois fois: Ça marche, mais maintenant j’ai trois copies de
.git/, trois historiques indépendants, et ungit fetchà faire dans chacun. Du gaspillage.Accepter la vie en série: Une feature après l’autre. Sûr, prévisible, et lent comme un merge sort à la main.
Aucune n’est cool. Mais il y a une quatrième option qui est dans git depuis 2015 et que presque personne utilise.
Worktrees: la solution que vous aviez déjà installée
Un worktree c’est un second répertoire de travail qui partage le même dépôt .git. Sans copies, sans clones, sans magie noire.
L’analogie: votre repo c’est une bibliothèque. Jusqu’à maintenant vous aviez une table où vous pouviez avoir qu’un livre ouvert. Un worktree c’est mettre plus de tables. Chacune avec un livre différent ouvert, mais toutes puisant dans la même étagère.
~/code/monapp/ ← table 1 (main)
.git/ ← la bibliothèque (une seule)
~/code/monapp-sparkline/ ← table 2 (feature/sparkline)
.git ← fichier, pas dossier (pointeur vers la bibliothèque)
~/code/monapp-notifications/ ← table 3 (feature/notifications)
.git ← autre pointeur
Chaque répertoire est un checkout complet avec tous les fichiers. Vous pouvez compiler dans l’un, faire tourner les tests dans l’autre, et avoir votre agent d’IA qui bosse dans le troisième. En même temps.
Le créer c’est une ligne
Depuis votre repo principal:
| |
C’est tout. Deux répertoires nouveaux, chacun dans sa branche, partageant toute la base de données git. Pas besoin de cloner, pas besoin de configurer des remotes, pas besoin de dupliquer l’historique.
Ce qu’ils partagent et ce qu’ils partagent pas
C’est important ça. Les worktrees partagent tout le repo: commits, branches, tags, remotes, hooks, configuration. Si vous faites un commit dans le worktree de sparkline, vous pouvez le voir immédiatement depuis celui des notifications sans faire de fetch ni rien, parce que c’est la même base de données.
Ce qu’ils partagent pas:
- Les fichiers sur disque (chaque table a sa copie de travail)
- Le staging area (chacun a son propre
git add) - Le HEAD (chacun pointe vers sa branche)
Dit en bon français: l’état de “sur quoi je bosse” est privé à chaque worktree. Tout le reste est commun.
Le workflow avec les coding agents
C’est là que ça devient intéressant. Avec les worktrees, vous pouvez littéralement avoir plusieurs agents qui bossent en parallèle sur le même projet:
| |
Chaque instance de Claude a son propre répertoire, sa propre branche, son propre .build/. Ils se marchent pas dessus. Ils se disputent pas l’index. Ils ont pas besoin de faire stash de quoi que ce soit.
Et comme ils partagent la base de données git, quand un des agents termine et fait push, les autres voient déjà cette branche.
Merger: exactement pareil qu’avant
Les worktrees changent rien au flux de merge. Ce sont des branches normales dans des répertoires séparés:
| |
Quand vous avez terminé, vous nettoyez:
| |
Les pitfalls que personne vous dit
1. Une branche, un worktree
Vous pouvez pas avoir main checkée dans deux worktrees en même temps. C’est by design: ça évite que deux répertoires modifient le même HEAD et se corrompent. Si vous avez besoin d’un second checkout de main, créez une branche temporaire.
2. Le premier build est depuis zéro
Chaque worktree a son propre répertoire de build. La première compilation va être lente. Après, chaque worktree maintient son cache indépendant, ce qui est précisément l’avantage par rapport au git checkout classique (qui vous invalide le cache à chaque fois que vous changez de branche).
3. Fichiers locaux non trackés
Votre .env.local, configurations d’éditeur, fichiers qui sont pas dans git… se copient pas vers le nouveau worktree. Vous devrez les recréer ou faire des symlinks.
4. Apps avec état partagé sur disque
Si votre app écrit des données dans ~/Library/Application Support/ ou similaire, deux instances de l’app depuis différents worktrees vont se disputer le même fichier. C’est pas un problème du worktree, c’est un problème de faire tourner deux instances de la même app. La solution: en faire tourner qu’une seule à la fois, ou paramétrer le répertoire de données par build.
5. Supprimez pas le répertoire à la main
Si vous faites rm -rf du worktree au lieu d’utiliser git worktree remove, git pense toujours que la branche est occupée. Exécutez git worktree prune pour nettoyer les références orphelines.
6. Le remote sait rien
Les worktrees sont 100% locaux. Gitea, GitHub, GitLab… aucun remote sait qu’ils existent. Ils voient que des git push normaux avec des branches normales. C’est comme demander si votre serveur a des problèmes avec le fait que vous utilisez Vim ou VS Code: il le sait pas, ça l’affecte pas.
Bonnes pratiques
Convention de nommage: mettez les worktrees comme frères du repo original, avec un suffixe descriptif:
~/code/monapp/ ← main
~/code/monapp-sparkline/ ← feature
~/code/monapp-notifications/ ← feature
~/code/monapp-hotfix-login/ ← hotfix
Comme ça un ls ~/code/monapp* vous montre tout d’un coup d’œil.
Un worktree par feature, pas par caprice: créez des worktrees pour du travail qui va vraiment être parallèle. Si vous allez faire une chose après l’autre, une branche normale avec checkout suffit.
Nettoyez quand vous avez terminé: les worktrees abandonnés c’est comme les branches que personne supprime — ça s’accumule et ça embrouille. git worktree list c’est votre ami.
Éditez pas le même fichier depuis deux worktrees: techniquement vous pouvez, chacun a sa copie. Mais si les deux modifient le même fichier, vous aurez des conflits au merge. Essayez que les features touchent des zones différentes du code.
Proposition de workflow complète
Pour ceux qui veulent un flux de travail ordonné, voici celui que j’utilise:
| |
Le cycle c’est: créer → bosser en parallèle → push/PR → merge → nettoyer. Chaque worktree vit ce que vit la feature, ni plus ni moins.
Pour conclure
Les worktrees sont dans git depuis la version 2.5 (juillet 2015). Plus de dix ans. Et la plupart des gens continuent à faire git stash comme si on était en 2010.
Avec l’arrivée des coding agents, le goulot d’étranglement c’est plus la vitesse à laquelle vous écrivez du code — c’est la vitesse à laquelle vous pouvez changer de contexte. Et les worktrees éliminent complètement ce changement de contexte: vous changez pas de branche, vous changez de répertoire. cd au lieu de checkout.
Ce qui est, au bout du compte, ce qu’on aurait toujours dû faire.
TL;DR: git worktree add ../nom -b branche crée un second répertoire de travail sur le même repo. Sans copies, sans stash, sans invalider les caches. Parfait pour avoir plusieurs coding agents qui bossent en parallèle. Nettoyez avec git worktree remove quand vous avez terminé.