Aller au contenu principal

git worktree : travailler sur deux branches en même temps

git worktree permet de checkout plusieurs branches comme de vrais répertoires, en même temps — sans stash, sans perte de contexte. Gardez votre stack Docker en route pendant que vous traitez un hotfix en parallèle.

· 11 minutes de lecture
Voir la source
Christophe
Amoureux de Markdown, WSL et Docker ~ Curieux insatiable.
Claude Code
AI Assistant
Cet article existe aussi en anglais — lire la version originale.

Traduction automatique

Cette traduction a été produite par une IA. Elle peut contenir des contresens ou des maladresses, en particulier sur les termes techniques. En cas de doute, consultez l'article de référence en anglais — c'est lui qui fait foi.

Journal des modifications

Dernière
added a Docker-first demo of the hotfix scenario

git worktree : travailler sur deux branches en même temps

⚡
TL;DR

Vous êtes plongé dans une branche de feature — du code à moitié écrit, des containers Docker qui tournent, des fichiers ouverts partout. Et là : « hotfix urgent à faire sur main ». Avec le workflow habituel, vous stashez tout, vous changez de branch, vous corrigez, vous committez, vous poussez, puis vous dépilez le stash en espérant que rien n'explose. Avec git worktree, vous checkoutez une deuxième branch dans un dossier séparé. Les deux branches existent en même temps, comme de vrais répertoires, avec leurs propres terminaux et leurs propres stacks Docker.

Il est 15h, un jeudi. Vous travaillez sur une nouvelle fonctionnalité depuis deux jours. Les containers Docker tournent, votre éditeur a huit fichiers ouverts, et vous êtes au milieu d'un refactoring qui ne compile pas encore.

Votre téléphone vibre. La production est cassée. Un correctif doit partir sur main dans les trente minutes.

Vous faites quoi ?

Le workflow du stash et sa douleur​

L'approche classique :

>user@machine: ~/yourproject

Ça marche. La plupart du temps. Mais :

  • Vos containers Docker pointent maintenant vers le mauvais code — il faut les redémarrer
  • Votre éditeur a perdu le contexte — tous ces fichiers ouverts ont disparu ou pointent vers les versions de main
  • Si git stash pop part en conflit, vous voilà avec un joyeux bazar à trois branches à résoudre, encore sous le stress du hotfix
  • Vous ne pouvez avoir qu'une seule branch active à la fois

Le problème de fond : un git stash est un état fragile. Ce n'est pas une branch. Il n'a pas d'historique. Il peut entrer en conflit. Et il disparaît dès que vous le dépilez.

Puisqu'on parle de jongler avec les branches : Git - Quelques astuces pour votre fichier .gitconfig montre comment trier git branch par date du dernier commit, et Afficher les 3 dernières branches modifiées quand vous entrez dans un repo git les affiche automatiquement quand vous entrez dans un repository.

Ce que fait git worktree​

Un git worktree est un deuxième (ou troisième, ou quatrième) répertoire de travail lié au même repository git.

Au lieu d'un dossier avec une seule branch checkoutée, vous obtenez :

~/projects/my-blog/ ← main branch (original)
~/projects/my-blog-hotfix/ ← hotfix/invoice-fix branch (worktree)
~/projects/my-blog-feature-auth/ ← feature/auth branch (worktree)

Chaque dossier est un vrai répertoire avec ses propres fichiers, son propre terminal, ses propres processus en cours. Ils partagent la même base .git (commits, objets, historique), mais chacun a une branch checkoutée indépendamment.

Vous ne quittez jamais votre branch de feature. Le hotfix vit juste à côté.

Les commandes de base​

Ajouter un worktree​

>user@machine: ~/yourproject

Crée un nouveau répertoire à l'emplacement <path> avec [branch] checkoutée :

>user@machine: ~/yourproject

Si la branch n'existe pas encore, créez-la en même temps :

>user@machine: ~/yourproject

Cela crée hotfix/invoice-fix à partir de main, checkoutée dans ../my-blog-hotfix.

Lister tous les worktrees​

>user@machine: ~/yourproject

Sortie :

/home/christophe/projects/my-blog a4b2c1d [main]
/home/christophe/projects/my-blog-hotfix e8f3d2a [hotfix/invoice-fix]

Supprimer un worktree​

>user@machine: ~/yourproject

Cela supprime le dossier et désenregistre le worktree. La branch elle-même (hotfix/invoice-fix) existe toujours — vous pouvez la supprimer séparément avec git branch -d.

Le voir en action avec Docker​

git n'a pas besoin d'être installé — il est déjà sur votre machine. Ce qui vaut la peine d'être testé sans risque, c'est le scénario lui-même : un repo jetable, déjà en plein refactoring sur une branch de feature avec des modifications non committées, et un bug de calcul de TVA qui attend sur main. Exactement la situation du jeudi après-midi ci-dessous, sans le stress.

Pourquoi Docker d'abord ?

Le Dockerfile ci-dessous construit un repo déjà positionné sur feature/user-notifications avec deux fichiers non stagés — le même point de départ que l'étape 1 ci-dessous — plus le navigateur fzf gwt décrit plus bas, branché via un vrai autoload ZSH. Rien n'est touché sur vos propres repos.

Construisez-le et lancez-le :

>user@machine: ~/worktree-demo

$ docker build -t worktree-demo . [+] Building 24.1s (8/8) FINISHED ✔ exporting to image

$ docker run --rm -it worktree-demo 🐳 root ~/projects/my-blog # git status On branch feature/user-notifications Changes not staged for commit: modified: src/api/notifications.ts modified: src/components/Notifications.tsx

C'est l'étape 1 ci-dessous, déjà en place. Maintenant, déroulez le reste du scénario pour de vrai, exactement comme écrit — git worktree add -b hotfix/invoice-fix ../my-blog-hotfix main, corrigez src/billing/invoice.ts dans le nouveau dossier, committez, git worktree remove, et vérifiez avec git status que votre branch de feature n'a pas bougé. gwt est branché aussi, si vous voulez essayer le navigateur fzf de la section « Une fonction ZSH » plus bas.

Lancez les commandes de l'étape 4 une par une

Ne collez pas tout le bloc de l'étape 4 d'un coup : vim est un éditeur plein écran, donc tout ce que vous collez après vim src/billing/invoice.ts est tapé dans vim au lieu d'être exécuté comme commandes shell. Lancez cette ligne seule, faites la modification (voir l'astuce à l'étape 4), sauvez et quittez, puis collez le reste. git push fonctionne aussi dans ce container — l'image branche un repo bare local comme origin, il y a donc une vraie cible où pousser, sans compte GitHub.

Le scénario du hotfix, étape par étape​

Retour au jeudi après-midi. Voici la même situation traitée avec des worktrees.

1. Vous êtes sur votre branch de feature, en plein travail​

>user@machine: ~/yourproject

Vous n'y touchez pas. Vous ne stashez rien.

2. Créez un worktree de hotfix à côté de votre projet​

>user@machine: ~/yourproject

git worktree add -b hotfix/invoice-fix ../my-blog-hotfix main

>user@machine: ~/yourproject

Preparing worktree (new branch 'hotfix/invoice-fix') HEAD is now at a4b2c1d chore: update dependencies

3. Ouvrez un nouveau terminal, allez dans le dossier du hotfix​

>user@machine: ~/yourproject

Ce répertoire contient les fichiers de main. Le répertoire de votre branch de feature est intact, toujours en cours d'exécution, toujours ouvert dans votre éditeur.

4. Corrigez le bug et poussez​

>user@machine: ~/yourproject

Le vrai correctif TVA

calculateVat() retourne amount * rate — juste la part de TVA, pas le total de la facture. Dans vim : appuyez sur i, changez la ligne en return amount * (1 + rate);, puis Esc suivi de :wq pour sauver et quitter. Seulement ensuite, lancez les lignes git add/commit/push.

5. Nettoyez le worktree​

>user@machine: ~/yourproject

Pourquoi -D et pas -d

Vous êtes toujours sur feature/user-notifications ici, qui n'a jamais reçu le commit du hotfix — seul origin/hotfix/invoice-fix l'a reçu, via la PR mergée. git branch -d refuse de supprimer une branch qu'il ne voit pas comme mergée dans votre branch courante, et sort l'erreur « not fully merged ». Comme vous savez qu'elle est bien mergée sur le remote, -D (force) est le bon choix, pas un contournement d'erreur.

6. Retour à votre branch de feature — rien n'a changé​

>user@machine: ~/yourproject

Pas de stash, pas de conflits, pas de changement de contexte.

Une contrainte : une branch ne peut être que dans un seul worktree à la fois​

Git l'impose. Si feature/user-notifications est checkoutée dans votre répertoire principal, vous ne pouvez pas ajouter un second worktree avec la même branch. Si vous essayez :

>user@machine: ~/yourproject

C'est volontaire — deux répertoires écrivant simultanément sur la même branch corrompraient l'arbre de travail. Chaque worktree a sa propre branch.

Docker + worktrees : chaque branch a sa propre stack​

C'est là que les worktrees deviennent vraiment puissants dans un workflow Docker.

Chaque worktree est un répertoire séparé. Chaque répertoire peut avoir son propre fichier .env et sa propre stack Docker Compose en route, tant que vous évitez les conflits de ports.

Une convention pratique : un port différent par worktree. Gardez les ports dans .env, qui est dans le .gitignore :

>user@machine: ~/yourproject

Vous pouvez maintenant lancer les deux stacks en même temps :

>user@machine: ~/yourproject

// Terminal 1 — branch de feature cd ~/projects/my-blog docker compose up

// Terminal 2 — branch de hotfix cd ~/projects/my-blog-hotfix docker compose up

Les deux serveurs tournent en même temps. Vous pouvez tester le hotfix sur http://localhost:3001 sans arrêter le développement de votre feature sur http://localhost:3000.

Projets Compose nommés

Docker Compose utilise le nom du dossier comme nom de projet par défaut. Comme vos worktrees sont dans des dossiers différents, Compose crée automatiquement des réseaux et des ensembles de containers séparés — aucune configuration supplémentaire n'est nécessaire.

Une fonction ZSH pour naviguer entre les worktrees​

Si vous suivez le pattern du workflow ZSH modulaire, vous pouvez ajouter un navigateur interactif de worktrees basé sur fzf :

Utilisation :

gwt # fzf picker — select any active worktree and cd into it
gwt feature/dark-mode # create + cd into a new worktree for that branch

Astuces pratiques​

Nommez les worktrees de manière cohérente​

Un schéma de nommage prévisible évite la confusion :

# Pattern: <repo-name>-<branch-slug>
git worktree add ../my-blog-hotfix-invoice hotfix/invoice-fix
git worktree add ../my-blog-feat-auth feature/auth

Les worktrees fonctionnent avec VS Code​

Ouvrez un dossier de worktree dans une nouvelle fenêtre VS Code :

>user@machine: ~/yourproject

Chaque fenêtre fonctionne indépendamment, avec ses propres fichiers ouverts et ses propres sessions de terminal.

Élaguez les worktrees obsolètes​

Si vous supprimez manuellement un dossier de worktree (au lieu d'utiliser git worktree remove), git peut encore croire qu'il existe. Nettoyez les références obsolètes :

>user@machine: ~/yourproject

Conclusion​

git stashgit worktree
Changement de branchOui, obligatoireNon — les branches coexistent
Containers DockerÀ redémarrerTournent indépendamment
Contexte de l'éditeurPerduPréservé
Développement parallèleNonOui
Risque de conflitAu stash popAucun
NettoyageAutomatique au popManuel : worktree remove

Le stash reste utile pour les petits trucs rapides — économiser une demi-ligne de frappe avant un git pull. Dès qu'il s'agit de services en cours d'exécution, d'une session d'éditeur ou de plus de cinq minutes de travail, un worktree est plus propre.

La première fois que vous traiterez un hotfix sans quitter votre branch de feature, vous vous demanderez comment vous avez pu travailler autrement.


🦋 Rejoignez la conversation sur BlueskyUn compte Bluesky gratuit est nécessaire pour aimer, repartager ou commenter. Ce bloc interroge l'API publique de Bluesky directement depuis votre navigateur (sans cookie, sans connexion) — votre adresse IP parvient donc aux serveurs de Bluesky dès que cette section se charge.

Chargement des commentaires…

Cet article vous a-t-il été utile ?
Avez-vous suivi les étapes de cet article ?