Dédoublez-vous avec les worktrees
Par Maxime Bréhin • Publié le 18 oct. 2021

Mise à jour le 24 novembre 2021, 15:41

Peut-être connaissez-vous le stash qui sert à mettre du travail de côté ? Git worktree vous permet en quelque sorte de faire la même chose. La différence est que les worktrees vous permettent de laisser votre espace de travail en l’état et en créent un autre ailleurs sur votre disque. Cet autre espace de travail aura la particularité de pointer sur le même dépôt local que le dépôt initial mais pointera sur une autre branche.

Vous préférez une vidéo ?

Si vous êtes du genre à préférer regarder que lire pour apprendre, on a pensé à vous :

Fonctionnement de Git worktree

Quand est-ce utile ?

Il y a 2 situations "classiques" pour lesquelles l’usage des worktrees peut s’avérer plus adapté que le stash.

Staging complexe à préserver

Si on a déjà bien avancé sur le staging de notre travail, il serait frustrant de voir à terme le stash pop refuser de le restaurer, au prétexte qu'on aura entre-temps modifié certains des fichiers concernés par notre stage.

On utilise alors git worktree pour créer un autre répertoire projet pointant sur le même dépôt local que notre projet actuel. On pourra travailler sereinement sur une autre branche puis reprendre, dans notre répertoire initial, notre commit en cours de préparation.

Bascule régulière entre branches impactant l'environnement

En soi, basculer régulièrement entre deux branches (par exemple une branche de fonctionnalité et une de correctifs urgents) n'entraîne pas forcément de lourdeur particulière, et le stash reste un mécanisme rapide et agile.

Cependant, il arrive qu'on doive régulièrement basculer entre des branches très différentes les unes des autres, par exemple entre notre développement fonctionnel courant et de la maintenance corrective sur une version déjà ancienne. Même lorsqu'elles ne sont pas si éloignées, nos branches peuvent aussi nécessiter à chaque restitution sur notre working directory un lourd travail de recompilation d'artefacts voire de réinstallation de dépendances.

Afin d'éviter de perdre un temps considérable à chaque bascule, on peut alors faire co-exister ces branches sur le disque, chacune dans son worktree.

Utiliser les worktrees pour des branches fréquentes mais lourdes à activer

Mise en œuvre

Pour initialiser un worktree depuis notre dépôt courant nous devons exécuter la commande :

git worktree add -b <branche-à-créer> ../<nouveau-répertoire> <point de départ>

L’option -b permet d’indiquer le nom de la nouvelle branche à créer. Si cependant on souhaite utiliser une branche déjà exitante, il suffira de ne pas renseigner cette option et de passer le nom de la branche voulue en dernier argument (« point de départ »).

Voici deux exemples d’utilisation :

# Si la branche sur laquelle vous souhaitez travailler n’existe pas
# (ici « fix/payment »), vous devrez la créer « à la volée » en lui
# désignant son point de départ (ici la branche « main »).
git worktree add -b fix/payment ../project-fix-payment main

# Si elle existe, vous n’avez qu’à la désigner directement (ici « release-1 »)
git worktree add ../project-release-1 release-1

Une fois notre worktree créé, il ne nous reste plus qu’à aller dans le répertoire associé pour travailler normalement sur notre branche.

État de mes worktrees

Lorsqu’on utilise les worktrees on souhaite parfois faire le point pour déterminer, par exemple, si on doit décider d’en supprimer certains (nettoyage).

Imaginez que vous ayez créé un worktree pour effectuer un correctif urgent de production :

git worktree add -b hotfix/protect-from-forgery ../project-hotfix-forgery production

Vous avez laissé le worktree sans trop vous en préoccuper. Puis un jour vous décidez de faire du nettoyage. Vous pourrez alors lister vos worktrees pour le projet courant en faisant un :

# Vous pouvez également utiliser l’option courte "-v"
git worktree list --verbose

Lister les worktrees

Supprimer un worktree

Vient le moment où un worktree n’est plus utile. Vous voudrez alors le supprimer :

git worktree remove <chemin-vers-votre-worktree>

En passant par cette commande vous garantissez que vous ne supprimez pas un worktree ayant du travail en cours, lequel risquerait par conséquent d' être perdu (nouveaux fichiers, fichiers modifiés).

Si toutefois le worktree en question avait du travail en cours que vous estimez jetable, l’option -f (ou sa version verbeuse --force) vous permettra de contourner ce garde-fou :

git worktree remove -f <chemin-vers-votre-worktree>

Forcer la suppression d'un worktree

Oops ! J’ai supprimé le répertoire de mon worktree sans passer par la commande

Si on part du principe que vous n’avez pas ainsi jeté du travail en cours utile, pas de souci : il faut simplement « synchroniser » notre dépôt local pour qu’il prenne cette suppression en compte :

git worktree prune

Note : nous verrons plus loin la notion de verrouillage de worktrees ; si le worktree que vous tentez de supprimer est verrouillé, il faudra le déverrouiller d’abord, avec git worktree unlock <chemin-du-worktree>.

Déplacer un worktree

Vous pouvez déplacer ou renommer un répertoire de worktree :

git worktree move <chemin-actuel-du-worktree> <nouveau-chemin>

Là aussi, vous pourriez avoir renommé ou déplacé le dossier en direct, sans passer par Git. Vous pourrez alors faire appel à la fonction de réparation des worktrees depuis le worktree déplacé :

# Attention, seulement depuis Git 2.29 (janvier 2021)
git worktree repair

Réparer le chemin d’un worktree

Attention si vous travaillez avec des disques réseaux ou nomades

Si vous choisissez de placer vos worktrees sur un partage réseau ou un disque pouvant être retiré/déconnecté, vous devrez le signaler à Git pour éviter la purge de la référence quand il ne trouvera plus le worktree lors d’une opération de nettoyage interne (garbage collection).

Pour cela vous devrez verrouiller les worktrees concernés, soit dès la création avec :

git worktree add --lock --reason 'Sur le partage réseau' <chemin-vers-votre-worktree> <branche-ciblée>

…soit après, avec la commande :

git worktree lock --reason 'Sur le partage réseau' <chemin-vers-votre-worktree>

Ce verrouillage bloquera également la possibilité de supprimer ou déplacer le worktree désigné (via Git s’entend).

Bien évidemment, qui dit verrouillage dit aussi déverrouillage :

git worktree unlock <chemin-vers-votre-worktree>

Résumons tout ça

Vous l’aurez compris, les worktrees représentent une alternative utile au stash. Ils nous permettent de gérer plus facilement une bascule régulière entre deux branches sans avoir à en subir les lourdeurs éventuelles de restitution / mise en place.

Faites-en bon usage ! 😃

Découvrez nos cours vidéo ! 🖥

Nos cours vidéo sont un complément idéal et bon marché à nos articles techniques et formations présentielles. Autour de Git, de JavaScript et d’autres sujets, retrouvez des contenus de très grande qualité à des prix abordables, spécialement conçus pour lever vos plus gros points de blocage.