Lorsqu’une branche de version est en phase de tests de régression, un incident en production peut soudain imposer la création d’un correctif à partir d’un ancien commit, tandis que la compilation de la branche fonctionnelle doit se poursuivre. En enchaînant les git switch dans un même répertoire, les fichiers non suivis, l’état des scripts de build et les artefacts intermédiaires de Xcode risquent rapidement de se mélanger. Une approche plus fiable consiste à conserver un seul magasin d’objets Git sur un Mac cloud dédié, puis à créer avec Git Worktree un répertoire de travail distinct pour chaque tâche.
Worktree sert à isoler les états, pas à accélérer les changements de branche
La méthode habituelle pour travailler dans plusieurs répertoires consiste à cloner plusieurs fois le dépôt. Sur une base de code volumineuse, cela duplique les objets Git, les temps de téléchargement et les efforts de maintenance. Worktree partage le magasin d’objets sous-jacent, tout en fournissant à chaque répertoire son propre contenu extrait, son propre index et son propre HEAD. Il convient donc au traitement simultané des versions, des correctifs urgents et des développements fonctionnels.
En revanche, il n’isole pas automatiquement les artefacts Xcode. Si plusieurs arbres de travail continuent d’écrire dans le DerivedData par défaut, les index, caches de modules et fichiers intermédiaires peuvent toujours s’écraser mutuellement. Il faut donc isoler à la fois les répertoires de sources et les sorties de build.
| Élément | Isolation automatique | Recommandation |
|---|---|---|
| Sources suivies | Oui | Utiliser une branche distincte pour chaque tâche |
| Fichiers non suivis | Oui | Ne pas stocker d’identifiants dans le répertoire du dépôt |
| Objets Git | Non | Les partager pour limiter l’occupation disque en double |
| DerivedData | Non | Définir un chemin distinct par arbre de travail |
| Journaux et bundles de résultats | Non | Utiliser des répertoires identifiés par branche |
L’intérêt de Worktree n’est pas d’accélérer une compilation isolée, mais de réduire la contamination invisible des états entre les tâches exécutées en parallèle.
Définir les règles de répertoires avant de créer les arbres de travail
Il est recommandé de placer le dépôt principal, les arbres de travail et les artefacts de build dans trois zones distinctes situées au même niveau. Cette séparation évite de supprimer par erreur des résultats de test encore nécessaires à l’archivage lors du retrait d’un arbre de travail.
~/projects/mobile-app
~/worktrees/release-3.4
~/worktrees/hotfix-3.4.1
~/build-data/release-3.4
~/build-data/hotfix-3.4.1
Commencez par synchroniser les références distantes dans le dépôt principal, puis créez les arbres de travail :
cd "$HOME/projects/mobile-app"
git fetch --prune
mkdir -p "$HOME/worktrees" "$HOME/build-data"
git worktree add "$HOME/worktrees/release-3.4" release/3.4
git worktree add -b hotfix/3.4.1 \
"$HOME/worktrees/hotfix-3.4.1" origin/release/3.4
git worktree list
Par défaut, git worktree add interdit d’extraire simultanément une même branche dans deux arbres de travail. Il s’agit d’un mécanisme de protection qu’il ne faut pas contourner avec une option de forçage. Pour examiner uniquement un ancien commit, créez un arbre de travail en mode detached :
git worktree add --detach "$HOME/worktrees/audit-build" 8f32c1a
Établir une correspondance stable pour les noms de répertoires
Les noms de branches contiennent souvent des / et ne peuvent donc pas être repris tels quels pour former un nom de répertoire sur un seul niveau. Les scripts d’automatisation doivent remplacer les barres obliques et les espaces par des tirets, tout en conservant le nom de branche d’origine pour les opérations Git. Ils doivent également refuser les paramètres vides afin d’éviter toute écriture accidentelle dans le répertoire racine ou dans un répertoire partagé.
Attribuer un chemin de sortie distinct à chaque tâche Xcode
Une fois dans l’arbre de travail, utilisez -derivedDataPath pour fixer l’emplacement des artefacts intermédiaires et -resultBundlePath pour enregistrer les résultats de test ou les informations de diagnostic du build. Le chemin du bundle de résultats ne doit pas exister avant l’exécution ; un horodatage permet donc de générer un nom unique.
set -euo pipefail
BRANCH="${1:?branch required}"
SAFE_NAME="$(printf '%s' "$BRANCH" | tr '/ ' '--')"
WORKTREE="$HOME/worktrees/$SAFE_NAME"
OUTPUT="$HOME/build-data/$SAFE_NAME"
STAMP="$(date '+%Y%m%d-%H%M%S')"
mkdir -p "$OUTPUT/logs" "$OUTPUT/results"
cd "$WORKTREE"
xcodebuild \
-workspace MobileApp.xcworkspace \
-scheme MobileApp \
-configuration Debug \
-derivedDataPath "$OUTPUT/DerivedData" \
-resultBundlePath "$OUTPUT/results/$STAMP.xcresult" \
build 2>&1 | tee "$OUTPUT/logs/$STAMP.log"
Deux tâches peuvent également s’exécuter simultanément dans un même arbre de travail. Dans ce cas, une séparation par branche ne suffit plus : ajoutez un identifiant de tâche, par exemple release-3.4/job-17/DerivedData. Les tâches d’archivage doivent aussi utiliser un chemin d’archive spécifique afin qu’une tâche lancée plus tard n’écrase pas le résultat de la précédente.
Ne pas partager les caches de modules sans précaution
Le partage des caches semble économiser de l’espace, mais si deux branches utilisent des options de compilation, des chaînes d’outils ou des scripts de génération différents, un cache qui restitue un état incorrect sera plus difficile à diagnostiquer qu’une recompilation. Commencez par établir une base stable avec une configuration totalement isolée. N’envisagez le partage de ressources téléchargées en lecture seule qu’après avoir confirmé que les versions des outils, les fichiers de verrouillage des dépendances et les paramètres de build sont identiques, plutôt que de partager directement l’ensemble du DerivedData.
Effectuer quatre contrôles avant l’exécution en parallèle
Avant le premier build de chaque arbre de travail, consignez le commit, l’état du répertoire de travail et les paramètres de build réellement appliqués :
git rev-parse HEAD
git status --porcelain
xcodebuild -version
xcodebuild \
-workspace MobileApp.xcworkspace \
-scheme MobileApp \
-showBuildSettings > "$OUTPUT/build-settings.txt"
git status --porcelain ne doit produire aucune sortie. Si des fichiers générés sont présents, vérifiez d’abord s’ils doivent être ignorés au lieu de masquer le problème avec une commande de nettoyage. Lancez ensuite simultanément deux builds Debug à faible risque, puis vérifiez que les journaux, les bundles de résultats et les DerivedData sont bien enregistrés dans leurs répertoires respectifs.
Lors de la validation, contrôlez au minimum les points suivants :
- Les hachages de commit enregistrés par les deux tâches correspondent à leurs branches cibles.
- La suppression du DerivedData d’une tâche n’a aucun effet sur l’autre.
- Les noms des bundles de résultats, des journaux et des archives ne se répètent pas.
- Un journal d’échec permet de retrouver l’arbre de travail, le commit et la configuration de build.
- La mémoire et l’espace disque disponibles sur le système suffisent à exécuter les tâches en parallèle.
Supprimer en toute sécurité les arbres de travail et les artefacts de build
Avant toute suppression, accédez à l’arbre de travail concerné, exécutez git status --short et vérifiez qu’aucun processus xcodebuild n’est encore actif. Déplacez hors du répertoire temporaire les journaux, bundles de résultats et archives à conserver. Exécutez ensuite les commandes suivantes depuis le dépôt principal :
cd "$HOME/projects/mobile-app"
git worktree remove "$HOME/worktrees/hotfix-3.4.1"
git worktree prune
git worktree list
Si le répertoire contient des modifications non validées, git worktree remove refuse l’opération. N’utilisez pas --force comme méthode de nettoyage courante : commencez par valider les changements, les mettre de côté dans un emplacement clairement identifié ou confirmer manuellement leur abandon. Supprimez également les artefacts de build répertoire de tâche par répertoire de tâche, sans utiliser de caractères génériques dont la portée est incertaine.
Pour une exploitation de longue durée, le registre des arbres de travail peut être intégré au système de gestion des tâches afin de consigner la branche, le responsable, la date de création, le répertoire de sortie et la date de libération prévue. Cette pratique évite que des répertoires abandonnés continuent d’occuper le SSD, tout en empêchant la suppression accidentelle d’un environnement de correctif encore utilisé.
Questions fréquentes
Une même branche Git peut-elle être ouverte dans deux Worktrees ?
Pas par défaut. Il faut créer des branches distinctes pour les modifications simultanées, ou utiliser un Worktree détaché pour une simple vérification.
Plusieurs Worktrees peuvent-ils partager DerivedData ?
Ce n’est pas recommandé. Les builds simultanés peuvent écraser les index, caches de modules et fichiers intermédiaires. Chaque Worktree doit avoir son propre chemin.
Que faut-il vérifier avant de supprimer un Worktree ?
Vérifiez l’absence de modifications non validées et de processus xcodebuild actifs, puis conservez les archives, résultats et journaux encore nécessaires.
Conserver un environnement reproductible sur le même Mac dans le cloud
Choisissez un modèle, une région et une durée de location fixes, puis utilisez l’interface graphique complète de macOS et la ligne de commande pour vos tâches de développement ou d’automatisation.