git worktree attache plusieurs répertoires de travail à un même dépôt.
Chacun est positionné sur sa propre branche, dans son propre dossier, et tous
partagent le même historique. Vous traitez une urgence sur hotfix/timeout-api
pendant que votre travail en cours reste intact sur main, sans stash et sans
second clone. Ce guide montre comment créer un worktree, ce qu'il contient
réellement, pourquoi Git refuse la même branche deux fois, et ce que deux
worktrees ne partagent pas, qui est la source de la plupart des mauvaises
surprises.
Prérequis : Les branches en bref et Enregistrer des modifications.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Créer un second répertoire de travail avec
git worktree add - Distinguer ce que les worktrees partagent de ce qu'ils dupliquent
- Diagnostiquer les deux refus les plus fréquents de Git
- Supprimer, déplacer et réparer un worktree proprement
- Choisir entre un worktree, un
git stashet un second clone
Qu'est-ce qu'un worktree Git ?
Section intitulée « Qu'est-ce qu'un worktree Git ? »Un worktree, ou répertoire de travail, est le dossier dans lequel vous voyez
et modifiez vos fichiers. Par défaut, un dépôt en possède exactement un, créé
par git init ou git clone. Changer de branche y transforme les fichiers sur
place, ce qui explique pourquoi Git refuse de basculer quand vous avez des
modifications en cours.
git worktree lève cette contrainte. La commande crée un worktree lié, un
second dossier rattaché au même dépôt, positionné sur une autre branche.
Les deux dossiers partagent l'historique, les branches, les tags et les remotes,
mais possèdent chacun leur HEAD, leur index et leurs fichiers. Aucun git push ni git fetch n'est nécessaire entre eux : un commit créé dans l'un est
immédiatement visible depuis l'autre, puisqu'il n'y a qu'un seul dépôt.
Worktree, stash ou clone : lequel choisir ?
Section intitulée « Worktree, stash ou clone : lequel choisir ? »Les trois répondent au même besoin de départ, travailler ailleurs sans perdre l'état courant, mais avec des coûts très différents.
| Approche | Ce qu'elle coûte | Quand la préférer |
|---|---|---|
git stash | Met le travail en pile, le dossier revient à un état propre | Interruption courte, quelques minutes, sur la même base de dépendances |
| Second clone | Duplique l'historique complet, exige push/fetch pour échanger | Machine différente, ou besoin d'un dépôt réellement indépendant |
git worktree | Un dossier de plus, historique partagé, commits visibles des deux côtés | Travail parallèle prolongé, ou branches aux dépendances incompatibles |
Le cas qui tranche vraiment en faveur du worktree est celui des dépendances
incompatibles. Migrer un projet vers une version majeure de framework change
tout le contenu de node_modules. Avec un seul dossier, chaque aller-retour
entre la branche de production et la branche de migration impose une
réinstallation complète et une purge des caches. Avec deux worktrees, les deux
environnements coexistent, chacun installé une fois, et vous passez de l'un à
l'autre par un simple cd.
Comment créer un worktree pour un correctif urgent ?
Section intitulée « Comment créer un worktree pour un correctif urgent ? »Le scénario est celui d'un dépôt api-meteo où une modification est en cours,
non committable en l'état, quand un correctif urgent devient prioritaire.
-
Constater le travail en cours : le dossier principal n'est pas propre.
Fenêtre de terminal git status --shortM api.py -
Créer le worktree avec sa branche, en une commande. L'option
-bcrée la branche, le dernier argument est le chemin du nouveau dossier, ici un dossier voisin.Fenêtre de terminal git worktree add -b hotfix/timeout-api ../api-meteo-hotfixPreparing worktree (new branch 'hotfix/timeout-api')HEAD is now at 04de30c feat: premiere version de l'api meteo -
Vérifier la liste des répertoires de travail attachés au dépôt. Le principal apparaît toujours en premier.
Fenêtre de terminal git worktree list/home/dev/projets/api-meteo 04de30c [main]/home/dev/projets/api-meteo-hotfix 04de30c [hotfix/timeout-api] -
Constater que le travail en cours est intact dans le dossier principal : rien n'a été déplacé ni mis en pile.
Fenêtre de terminal git status --shortM api.py -
Corriger et committer depuis le nouveau dossier, comme dans n'importe quel dépôt.
Fenêtre de terminal cd ../api-meteo-hotfixgit commit -am "fix: augmente le timeout de l'api" -
Retrouver le commit depuis le dossier principal, sans aucune synchronisation. Le dépôt est commun.
Fenêtre de terminal cd ../api-meteogit log --oneline hotfix/timeout-api -14bbf040 fix: augmente le timeout de l'api
Sans -b, git worktree add ../api-meteo-hotfix crée automatiquement une
branche portant le nom du dernier segment du chemin, ici api-meteo-hotfix.
Nommer explicitement la branche avec -b évite ces branches involontaires.
Que contient réellement un worktree lié ?
Section intitulée « Que contient réellement un worktree lié ? »Un worktree lié ne contient pas de dossier .git, mais un fichier .git
de quelques dizaines d'octets. C'est la différence la plus visible avec un clone,
et elle explique le coût quasi nul de l'opération.
ls -la ../api-meteo-hotfix/.gitcat ../api-meteo-hotfix/.git-rw-rw-r-- 1 dev dev 154 juil. 28 13:42 ../api-meteo-hotfix/.gitgitdir: /home/dev/projets/api-meteo/.git/worktrees/api-meteo-hotfixCe fichier est un simple pointeur vers un sous-dossier de métadonnées créé
dans le dépôt principal. C'est là que vivent le HEAD et l'index propres à ce
worktree, pendant que les objets, les branches et les tags restent partagés.
Répertoireapi-meteo/
Répertoire.git/
Répertoireworktrees/
Répertoireapi-meteo-hotfix/
- HEAD
- index
- gitdir
- commondir
- api.py
Répertoireapi-meteo-hotfix/
- .git
- api.py
Conséquence pratique : l'historique n'est jamais dupliqué. Sur un dépôt dont
le dossier .git pèse plusieurs centaines de mégaoctets, un worktree
supplémentaire ne coûte que la taille des fichiers réellement présents dans la
branche, là où un second clone recopierait tout.
Pourquoi Git refuse la même branche dans deux worktrees ?
Section intitulée « Pourquoi Git refuse la même branche dans deux worktrees ? »Une branche ne peut être active que dans un seul worktree à la fois. Tenter d'ouvrir un second dossier sur une branche déjà utilisée échoue immédiatement.
git worktree add ../api-meteo-copie mainPreparing worktree (checking out 'main')fatal: 'main' is already used by worktree at '/home/dev/projets/api-meteo'Ce refus est une protection, pas une limitation arbitraire. Deux dossiers positionnés sur la même branche pourraient committer chacun de leur côté et faire diverger silencieusement le même pointeur. Le message indique le chemin exact du worktree fautif, ce qui suffit en général à comprendre la situation.
Depuis n'importe quel worktree, git branch -v marque d'un + les branches
occupées par un autre répertoire de travail, en plus de l'astérisque habituel
pour la branche courante.
git branch -v+ hotfix/timeout-api 4bbf040 fix: augmente le timeout de l'api* main 04de30c feat: premiere version de l'api meteoSi vous avez réellement besoin de la même branche deux fois, --force passe
outre, mais c'est un aveu d'organisation bancale : préférez une branche par
worktree.
Comment supprimer, déplacer et réparer un worktree ?
Section intitulée « Comment supprimer, déplacer et réparer un worktree ? »Supprimer proprement
Section intitulée « Supprimer proprement »git worktree remove efface le dossier et ses métadonnées. La commande refuse
de détruire du travail non committé.
git worktree remove ../api-meteo-hotfixfatal: '../api-meteo-hotfix' contains modified or untracked files, use --force to delete itAprès un --force assumé, ou une suppression sur un dossier propre, la branche
survit : seul le répertoire de travail disparaît, le travail committé reste
dans le dépôt.
git worktree remove --force ../api-meteo-hotfixgit branch -v hotfix/timeout-api 4bbf040 fix: augmente le timeout de l'api* main 04de30c feat: premiere version de l'api meteoNettoyer après une suppression manuelle
Section intitulée « Nettoyer après une suppression manuelle »Supprimer le dossier avec rm -rf sans prévenir Git laisse une entrée
obsolète. Elle apparaît alors annotée prunable dans la liste.
git worktree list/home/dev/projets/api-meteo 04de30c [main]/home/dev/projets/api-meteo-audit 04de30c (detached HEAD) prunablegit worktree prune fait le ménage, avec un mode simulation qui explique ce
qu'il retirerait.
git worktree prune --dry-run --verboseRemoving worktrees/api-meteo-audit: gitdir file points to non-existent locationDéplacer, et réparer après un déplacement manuel
Section intitulée « Déplacer, et réparer après un déplacement manuel »git worktree move déplace un worktree en mettant à jour les métadonnées. Un
mv fait à la main casse le lien : le dossier continue de fonctionner, mais le
dépôt principal ne sait plus où il est et le marque prunable, ce qui l'expose à
être purgé au prochain prune. La réparation tient en une commande, lancée
depuis le dépôt principal avec le nouveau chemin en argument.
git worktree repair ../api-meteo-cache-finalrepair: gitdir incorrect: /home/dev/projets/api-meteo/.git/worktrees/api-meteo-cache/gitdirVerrouiller un worktree
Section intitulée « Verrouiller un worktree »Un worktree stocké sur un disque amovible ou un montage réseau disparaît quand le
support est détaché, et Git le considère alors comme purgeable. git worktree lock l'en protège, avec une raison consultable.
git worktree lock --reason "disque externe" ../api-meteo-cache-finalgit worktree remove ../api-meteo-cache-finalfatal: cannot remove a locked working tree, lock reason: disque externeuse 'remove -f -f' to override or unlock firstCe que deux worktrees ne partagent pas
Section intitulée « Ce que deux worktrees ne partagent pas »C'est ici que se logent les mauvaises surprises. Git partage tout ce qui vit dans le dépôt, et rien de ce qui vit dans le répertoire de travail. Or l'essentiel d'un environnement de développement moderne est justement dans le répertoire de travail, et souvent ignoré par Git.
| Élément | Partagé | Conséquence concrète |
|---|---|---|
| Historique, branches, tags, remotes | Oui | Un commit est visible des deux côtés, sans push |
| Stash | Oui | La pile de stash est commune au dépôt |
Hooks (.git/hooks/) | Oui | Aucun hook par worktree, ils s'appliquent partout |
node_modules, venv, vendor | Non | Réinstallation complète dans chaque nouveau worktree |
Fichiers non versionnés (.env) | Non | Absents du nouveau dossier, à recopier à la main |
| Caches de build | Non | Première compilation à froid dans chaque worktree |
Les fichiers non versionnés sont le piège le plus courant. Un .env exclu
par le .gitignore n'existe pas dans le nouveau worktree, et l'application y
échoue sur une variable manquante, sans rapport apparent avec la manipulation Git
qui vient d'être faite. Le coût disque vient juste après : un dossier de
dépendances de plusieurs centaines de mégaoctets est payé autant de fois qu'il y
a de worktrees.
Les hooks, à l'inverse, surprennent parce qu'ils sont partagés. Comme ils
vivent dans .git/hooks/, un hook de pre-commit s'applique dans tous les
worktrees, sans possibilité native d'en définir un par dossier.
Bonnes pratiques
Section intitulée « Bonnes pratiques »- Une branche, un worktree : ne forcez pas le partage d'une branche, la contrainte de Git protège de la divergence silencieuse.
- Nommez la branche avec
-bplutôt que de laisser Git la déduire du nom du dossier. - Placez les worktrees hors du dépôt principal, dans un dossier voisin
(
../projet-hotfix) et non à l'intérieur, sinon les fichiers du worktree apparaissent comme non suivis dans le dossier parent. - Copiez les fichiers d'environnement dès la création du worktree, c'est l'oubli le plus fréquent.
- Préférez
git worktree moveàmv, et gardezgit worktree repairen réserve quand le déplacement manuel a déjà eu lieu. - Supprimez avec
git worktree remove, pas avecrm -rf, pour éviter les entrées obsolètes. - Méfiez-vous des commandes destructrices lancées depuis le mauvais dossier : deux répertoires quasi identiques invitent à la confusion. Un script de déploiement qui travaille sur le dossier courant doit vérifier où il tourne.
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause | Solution |
|---|---|---|
fatal: 'main' is already used by worktree at ... | La branche est active dans un autre worktree | Utiliser une autre branche, ou fermer l'autre worktree |
fatal: ... contains modified or untracked files | Le worktree n'est pas propre | Committer, ou assumer git worktree remove --force |
Entrée annotée prunable dans git worktree list | Dossier supprimé ou déplacé à la main | git worktree prune si supprimé, git worktree repair avec le nouveau chemin si déplacé |
fatal: cannot remove a locked working tree | Le worktree est verrouillé | git worktree unlock ../api-meteo-cache-final puis relancer la suppression |
| L'application échoue sur une variable d'environnement | Les fichiers non versionnés n'ont pas suivi | Recopier .env et réinstaller les dépendances |
Une branche a disparu de git switch | Elle est occupée par un autre worktree | git branch -v et repérer la marque + |
À retenir
Section intitulée « À retenir »- Un worktree est un répertoire de travail supplémentaire attaché au même dépôt, pas une copie du dépôt.
- Le
.gitd'un worktree lié est un fichier pointeur, pas un dossier : l'historique n'est jamais dupliqué. - Une branche ne peut être active que dans un seul worktree, et
git branch -vmarque d'un+celles qui sont occupées ailleurs. - Un commit fait dans un worktree est immédiatement visible depuis les
autres, sans
pushnifetch. - Supprimer un worktree ne supprime pas sa branche, le travail committé reste dans le dépôt.
- Ce qui n'est pas versionné n'est pas partagé : dépendances,
.envet caches sont à refaire dans chaque worktree. - Les hooks sont partagés puisqu'ils vivent dans le dépôt commun.
git worktree repairdemande Git 2.30, l'option--orphandemande Git 2.42.
FAQ : git worktree
Section intitulée « FAQ : git worktree »Cinq questions qui reviennent quand on découvre les worktrees, à commencer par celle qui décide de l'adoption : la différence réelle avec un second clone. Les réponses reprennent en format court les points du guide sur le partage de l'historique, la contrainte d'une branche par worktree et le nettoyage.
| Second clone | git worktree |
|
|---|---|---|
| Historique | Dupliqué | Partagé |
| Échange entre les dossiers | push / fetch |
Immédiat, aucun transfert |
| Coût disque | Tout le dépôt | Seulement les fichiers de la branche |
| Branches et tags | Séparés | Communs |
.git est un simple fichier pointeur vers le dépôt principal, pas un dossier. Sur un dépôt dont le .git pèse plusieurs centaines de mégaoctets, la différence de coût est considérable.git worktree add ../api-meteo-copie main
fatal: 'main' is already used by worktree at '/home/dev/projets/api-meteo'
Sans cette protection, deux dossiers pourraient committer chacun de leur côté sur la même branche et la faire diverger silencieusement.Pour repérer les branches occupées, git branch -v les marque d'un + :+ hotfix/timeout-api 4bbf040 fix: augmente le timeout de l'api
* main 04de30c feat: premiere version de l'api meteo
--force permet de passer outre, mais c'est presque toujours le signe qu'une autre branche serait plus appropriée.git worktree remove ne touche qu'au répertoire de travail et à ses métadonnées. La branche et ses commits restent dans le dépôt :git worktree remove --force ../api-meteo-hotfix
git branch -v
hotfix/timeout-api 4bbf040 fix: augmente le timeout de l'api
* main 04de30c feat: premiere version de l'api meteo
La suppression de la branche reste une opération séparée et explicite (git branch -d hotfix/timeout-api). À noter : remove refuse de s'exécuter si le worktree contient des fichiers modifiés ou non suivis, ce qui protège le travail non committé.| Élément | Partagé entre worktrees |
|---|---|
| Historique, branches, tags | Oui |
| Stash | Oui |
Hooks (.git/hooks/) |
Oui |
node_modules, venv, vendor |
Non |
Fichiers non versionnés (.env) |
Non |
| Caches de build | Non |
.env manquant : l'application échoue sur une variable non définie, sans rapport visible avec la manipulation Git. Cette séparation est aussi un avantage quand deux branches ont des dépendances incompatibles, par exemple lors d'une migration de version majeure.prunable :/home/dev/projets/api-meteo-audit 04de30c (detached HEAD) prunable
Le nettoyage se fait avec prune, en simulant d'abord :git worktree prune --dry-run --verbose
Removing worktrees/api-meteo-audit: gitdir file points to non-existent location
Attention à ne pas confondre deux situations : si le dossier a été déplacé et non supprimé, ne lancez pas prune, qui couperait le lien définitivement. Utilisez git worktree repair suivi du nouveau chemin, qui rétablit la connexion.Pour aller plus loin
Section intitulée « Pour aller plus loin »- Git stash et git clean : l'alternative pour une interruption courte, quand créer un dossier serait disproportionné.
- HEAD détaché : comprendre l'état dans lequel se trouve un worktree créé avec
--detach. - Submodules : la combinaison la plus délicate avec les worktrees.
- Gestion des branches : nommer, lister et nettoyer les branches que vos worktrees occupent.