Pour quoi utiliser git-worktree?

211

J'ai lu le post de Github sur git-worktree . Ils écrivent:

Supposons que vous travaillez dans un référentiel Git sur une branche appelée feature, lorsqu'un utilisateur signale un bogue de haute urgence dans master. Vous créez d'abord un arbre de travail lié avec une nouvelle branche, hotfixextrait par rapport au maître […] Vous pouvez corriger le bogue, pousser le correctif et créer une demande d'extraction.

Lorsque je travaille sur une branche appelée fonctionnalité et qu'un bogue de haute urgence est signalé dans master, je cache généralement tout ce sur quoi je travaille et crée une nouvelle branche. Quand j'ai fini, je peux continuer à travailler. C'est un modèle très simple, je travaille comme ça depuis des années.

D'un autre côté, l'utilisation de git-worktree a ses propres limites:

Par exemple, il n'est pas autorisé d'avoir la même branche extraite dans deux arborescences de travail liées en même temps, car cela permettrait aux modifications validées dans une arborescence de travail de mettre l'autre hors de synchronisation.

Pourquoi devrais-je choisir un flux de travail plus compliqué pour un problème qui a déjà été résolu?

Y a-t-il quelque chose git-worktreequi ne pouvait pas être fait à l'avance et qui justifie cette toute nouvelle fonctionnalité complexe?

awendt
la source
12
Une chose que vous ne pouvez pas cacher est les chemins non fusionnés, après une fusion ou un rebase avec des conflits.
chirlu
11
Si vous travaillez avec des langues compilées, le stashing signifie que vous devrez tout recompiler lorsque vous décompressez.
mb14
Nous avons plusieurs produits différents basés sur le même code source (300 Mo), et je prévois de les combiner tous dans un grand référentiel et d'utiliser Worktree pour garder chaque produit extrait dans un dossier différent, plutôt que d'avoir un tas d'énormes clones qui ne restent pas synchronisés
endolith

Réponses:

197

Pour moi, git worktree est la plus grande amélioration depuis longtemps. Je travaille dans le développement de logiciels d'entreprise. Là, il est très courant de devoir conserver d'anciennes versions comme celles que vous avez publiées il y a 3 ans. Bien sûr, vous avez une branche pour chaque version afin que vous puissiez facilement y basculer et corriger un bug. Cependant, le changement est coûteux, car en attendant, vous avez complètement restructuré le référentiel et peut-être créer le système. Si vous changez, votre IDE fonctionnera fou en essayant d'adapter les paramètres du projet.

Avec worktree, vous pouvez éviter cette reconfiguration constante. Récupérez ces anciennes branches dans des dossiers séparés à l'aide de Worktree. Pour chaque branche, vous avez obtenu un projet IDE indépendant.

Bien sûr, cela aurait pu être fait dans le passé en clonant le dépôt plusieurs fois et c'est mon approche jusqu'à présent. Cependant, cela signifiait également gaspiller de l'espace sur le disque dur et, pire, avoir besoin de récupérer plusieurs fois les mêmes modifications dans le référentiel.

Sebi
la source
4
Vous n'avez pas eu à récupérer plusieurs fois les mêmes modifications dans le référentiel. Vous auriez pu simplement copier le répertoire .git du premier clone.
misiu_mp
1
@ jdk1.0 désolé pour la confusion, le commentaire était destiné à misiu_mp
mxttie
2
En tant que quelqu'un qui a utilisé 2-3 référentiels hautement répliqués afin de pouvoir créer une branche de fonctionnalité tout en développant sur une autre, j'avais chaque dépôt local comme télécommandes des autres et je suis entièrement d'accord avec les caractérisations des inconvénients de Sebi (beaucoup de récupération et de poussée! ) De plus, une fois que je passe à Worktree, je comprends que je n'aurai plus à me soucier de la divergence des branches locales portant le même nom (ce qui se produit environ une fois tous les 6 à 10 mois, car je suis interrompu plusieurs fois sur une période de plusieurs jours et je finis travailler la même branche de fonctionnalité à partir de plusieurs référentiels, mais oubliez de les synchroniser de nouveau ...)
sage
3
@iheanyi - (1). C'est plus rapide si l'EDI maintient des fichiers de données externes (tels que des bases de données d'indexation) associés à un répertoire donné. Si vous détruisez le contenu dans le même répertoire, cela invalidera généralement tous les caches de données IDE, et il devra être réindexé.
Steve Hollasch
5
@iheanyi - (2) Au fil du temps, l'histoire de tout augmentera beaucoup plus que les fichiers de l'arborescence de travail à un moment donné. L'histoire de tout == le .gitrépertoire. Avec de nombreux clones locaux en amont, vous disposez de nombreuses copies locales de la même base de données, car chaque clone possède sa propre .gitbase de données. Avec de nombreux arbres de travail locaux, chaque arbre utilise la même .gitbase de données. Oui, si vous avez des clones locaux de votre arbre de travail local, Git liera en dur une grande partie du contenu .git, mais pas sous Windows.
Steve Hollasch
71

Je peux voir quelques utilisations pour cela.

Si vous disposez d'une suite de tests qui s'exécute pendant une longue période, imaginez des heures et que vous la démarrez, elle bloque efficacement cette copie de travail jusqu'à la fin des tests. Changer de branche pendant ces tests les briserait d'une manière difficile à comprendre.

Ainsi, git-worktreeje pourrais avoir une deuxième idée lancée pour une autre branche qui y travaille.

De plus, lorsque je passe à une autre branche pour effectuer une enquête rapide, mon IDE pense que beaucoup de fichiers ont soudainement changé et indexeront toutes ces modifications, juste pour les réindexer lorsque je reviens.

Un troisième cas d'utilisation serait de faire une comparaison de fichiers en utilisant d'autres outils que git-diff, comme d'habitude diff, entre deux répertoires au lieu de deux branches.

Andreas Wederbrand
la source
6
Ne git clonefonctionnerait pas aussi bien pour tout cela?
2015 à 8h23
12
Cela ne ferait que cloner un grand référentiel à distance peut prendre beaucoup de temps. Je travaille sur un référentiel qui prend plusieurs minutes à cloner. Je suppose que tu pourrais le faire avec git clone --reference. De plus, la gestion de toutes les autres branches se fera une seule fois au lieu d'une fois par répertoire de travail.
Andreas Wederbrand
6
Ne clonez pas à partir de la télécommande, clonez à partir de votre local. Je ne comprends pas la question de la gestion des succursales, pouvez-vous clarifier?
2015
14
J'ai essayé d'utiliser des clones, et il y a vraiment un problème de gestion. Au lieu d'un seul ensemble de branches, j'ai un ensemble de clones, que je ne peux pas voir tous ensemble dans une seule interface utilisateur. Si j'ai besoin de choisir certains changements, je dois les récupérer ou les repousser. Il ajoute des étapes supplémentaires à toutes les actions. Tout est faisable, mais il y a toujours des frictions.
max630
2
Et quand il s'agit de configurer une sauvegarde, un référentiel unique est tellement plus facile.
max630
64

Une utilisation évidente consiste à comparer simultanément le comportement (et non la source) de différentes versions - par exemple différentes versions d'un site Web ou simplement une page Web.

J'ai essayé cela localement.

  • créer un répertoire page1.

  • à l'intérieur créer le répertoire srcet git initil.

  • en srccréer page1.htmlavec un peu de contenu et le valider.

  • $ git branch ver0

  • $ git worktree add ../V0 ver0

  • dans srcmaster, ajoutez plus de texte page1.htmlet validez-le.

  • $ git branch sty1

  • modifier page1.htmldans la sty1branche (ajouter un style CSS distinctif) et ajouter le valider.

  • $ git worktree add ../S1 sty1

Vous pouvez maintenant utiliser un navigateur Web pour ouvrir et afficher ces 3 versions simultanément:

  • ..\page1\src\page1.html // tout ce que git a comme courant

  • ..\page1\V0\page1.html // la version initiale

  • ..\page1\S1\page1.html // la version au style expérimental

RodMcGuire
la source
2
Je ne vois pas comment cela explique l'avantage d'utiliser worktree à cet effet sur un clone.
iheanyi
@iheanyi Vous pourriez en dire autant branch; la réponse est la même: elle est plus légère et conçue pour le travail.
OJFord
1
@OJFord c'est un peu le point. Cette réponse ne m'explique pas ce que fait Worktree qui est différent. Ce n'est évidemment pas un alias pour une branche ou un clone mais l'effet que je vois ici semble être le même. Je ne vois pas comment cela est plus léger que d'utiliser simplement une branche ou un clone.
iheanyi
@iheanyi C'est différent que d'utiliser une branche - vous ne pouvez pas utiliser des branches seules pour obtenir plusieurs états de worktree à la fois - et un poids plus léger qu'un deuxième (.., nième) clone. Ce que je voulais dire, c'est que vous pourriez dire aussi de la branche `` pourquoi ne pas simplement cloner et apporter vos modifications '', mais plusieurs branches dans un seul dépôt sont un poids plus léger et un moyen plus facile à gérer d'obtenir ce comportement.
OJFord
@OJFord Je ne pense pas que cela résout ma confusion avec Worktree. Permettez-moi de le dire ainsi, que vous utilisiez une branche ou un clone ou autre chose, l'objectif final du processus décrit ici est de comparer trois versions différentes de quelque chose simultanément. Sur la base de ce qui est dans la réponse, je ne comprends pas pourquoi j'utiliserais worktree sur une alternative. La réponse n'explique pas ce que fait Worktree alors que les alternatives ne le sont pas. Vous prétendez que quelque chose est léger (ou plus léger) mais je ne vois pas comment Worktree rend les branches moins "lourdes".
iheanyi
29
  1. Il existe des raisons légitimes pour lesquelles vous pouvez souhaiter / avoir besoin de plusieurs postes de travail dans le système de fichiers à la fois.

    • manipuler les fichiers extraits tout en ayant besoin d'apporter des modifications ailleurs (par exemple, compilation / test)

    • différencier les fichiers via des outils de diff normaux

    • pendant les conflits de fusion, je souhaite souvent parcourir le code source car il se trouve du côté source tout en résolvant les conflits dans les fichiers.

    • Si vous devez souvent basculer, vous perdez du temps à vérifier et à revérifier que vous n'avez pas besoin de faire avec plusieurs arbres de travail.

    • le coût mental du changement de contexte mental entre les branches via git stashing n'est pas vraiment mesurable. Certaines personnes trouvent qu'il y a un coût mental à ranger qui n'est pas là en ouvrant simplement des fichiers à partir d'un répertoire différent.

  2. Certaines personnes demandent "pourquoi ne pas faire plusieurs clones locaux". Il est vrai qu'avec le drapeau "--local" vous n'avez pas à vous soucier de l'utilisation d'espace disque supplémentaire. C'est (ou des idées similaires) ce que j'ai fait jusqu'à présent. Les avantages fonctionnels des postes de travail liés par rapport aux clones locaux sont les suivants:

    1. Avec les clones locaux, vos arbres de travail supplémentaires (qui se trouvent dans les clones locaux) n'ont tout simplement pas accès aux branches d'origine ou en amont. L '«origine» dans le clone ne sera pas la même que «l'origine» dans le premier clone.

      • Courir git log @{u}..ou git diff origin/feature/other-featurepeut être très utile et ce n'est plus possible ou plus difficile. Ces idées sont techniquement possibles avec des clones locaux via un assortiment de solutions de contournement, mais toutes les solutions de contournement que vous pourriez faire sont mieux et / ou plus simples grâce à des postes de travail liés.
    2. Vous pouvez partager des références entre des arbres de travail. Si vous souhaitez comparer ou emprunter des modifications à une autre succursale locale, vous pouvez maintenant le faire.

Alexander Bird
la source
11
Vous pouvez également répertorier tous les arbres de travail avec une seule commande, avec des clones dont vous avez besoin pour les suivre vous-même.
Ian Ringrose
hmm. Depuis git 2.7.0, cela semble être le cas. Bon à savoir.
Alexander Bird
9

tl; dr: Chaque fois que vous voulez faire vérifier deux arbres de travail en même temps pour une raison quelconque, git-worktreec'est un moyen rapide et peu encombrant de le faire.

Si vous créez un autre arbre de travail, la plupart des parties du référentiel (c'est-à-dire .git) seront partagées, ce qui signifie que si vous créez une branche ou récupérez des données pendant que vous êtes dans une arborescence de travail, elles seront également accessibles à partir de toutes les autres arborescences de travail que vous avez. Supposons que vous souhaitiez exécuter votre suite de tests sur branch foo sans avoir à la pousser quelque part pour la cloner, et que vous souhaitiez éviter les tracas du clonage de votre référentiel localement, l'utilisation git-worktreeest un bon moyen de créer simplement une nouvelle extraction d'un état dans un endroit séparé, temporairement ou définitivement. Tout comme avec un clone, tout ce que vous avez à faire lorsque vous en avez terminé est de le supprimer, et la référence à celui-ci sera récupérée après un certain temps.

jsageryd
la source
2
Les documents indiquent que vous ne pouvez pas avoir la même branche dans les deux copies de travail, ce qui constitue une sérieuse limitation. Avec Mercurial, cela n'a fonctionné qu'avec de petits problèmes.
hypersw
Sûr que vous pouvez. La page de manuel indique comment; chercher --force. Mais cela n'est pas pratique si vous mettez à jour la branche à un endroit et que vous comptez y travailler à un autre, car l'arbre de travail n'est pas mis à jour.
jsageryd
Oui, les succursales de Mercurial sont un concept plus transparent à cet égard. Comment les branches d'un arbre de travail apparaissent-elles dans l'autre? De la même manière que plusieurs liaisons montantes? Mes premières expériences avec des arbres de travail, avec l'exécution de la récupération dans les deux, se sont terminées avec deux (!) Pointeurs différents (!) Nommés origin/master.
hypersw
Un arbre de travail est (comme son nom l'indique) juste un arbre de travail, avec quelques fonctionnalités supplémentaires ajoutées; le référentiel est partagé entre tous les postes de travail. La seule différence entre deux arbres de travail est que la branche extraite peut être (et pour les flux de travail sains, est) différente. Il est possible de valider dans un arbre de travail séparé, il a donc également son propre index (aka zone de transfert) pour que cela fonctionne. Le .gitfichier dans l'arbre de travail séparé est un fichier texte contenant le chemin d'accès à sa configuration, qui réside dans le référentiel d'origine.
jsageryd
2
@WilsonF: git checkout --ignore-other-worktrees <branch> git-scm.com/docs/git-checkout/…
jsageryd
7

À l'origine, je suis tombé sur cette question après m'être demandé à quoi pouvaient servir ces fantastiques arbres de travail. Depuis, je les ai intégrés dans mon flux de travail et malgré mon scepticisme initial, je les ai trouvés très utiles.

Je travaille sur une base de code assez grande, ce qui prend un certain temps à compiler. J'ai généralement la branche de développement actuelle sur ma machine ainsi que la branche de fonctionnalités sur laquelle je travaille actuellement plus la branche principale, qui représente l'état actuel du système en direct.

L'un des plus grands avantages pour moi est évidemment que je n'ai pas à recompiler le tout à chaque fois que je change de branche (c'est-à-dire des arbres de travail). Un bon effet secondaire est que je peux aller dans le worktree de développement, y faire des trucs, changer le répertoire en worktree pour ma branche de fonctionnalité actuelle, puis le rebaser sans avoir à tirer en premier.

rethab
la source
4

J'en ai un assez inhabituel: je fais du développement Windows et Linux sur la même machine . J'ai une VirtualBox exécutant Linux à l'intérieur de ma boîte Windows. VirtualBox monte certains répertoires Windows et les utilise directement à l'intérieur de la machine Linux. Cela me permet d'utiliser Windows pour gérer les fichiers mais les construire sous Linux. Il s'agit d'un projet multiplateforme, il s'appuie donc sur Windows et Linux à partir de la même structure de répertoires.

Le problème est que les systèmes de construction Linux et Windows se plantent lorsqu'ils sont utilisés dans le même répertoire; il existe des étapes de construction compliquées pour le téléchargement de bibliothèques, etc., qui utilisent les mêmes noms de répertoire. La version Windows du système de build télécharge les bibliothèques spécifiques à Windows et la version Linux du système de build télécharge les bibliothèques spécifiques à Linux.

Dans un monde idéal, le système de construction serait modifié de sorte que Windows et Linux puissent coexister dans le répertoire, mais pour l'instant, le problème est résolu avec des arbres de travail. Le dossier "Linux" peut générer des artefacts de build spécifiques à Linux et le dossier "Windows" peut générer des artefacts de build spécifiques à Windows. Bien que ce ne soit pas une solution idéale, cela crée un joli trou d'arrêt en attendant que les bogues du système de construction soient résolus.

Certes, worktree n'a pas été conçu pour cela; Je dois garder la version Windows et la version Linux sur des branches distinctes, même si je préfère vraiment qu'elles soient sur la même branche. Pourtant, il fait le travail, et c'est un cas peu conventionnel de worktree sauver la journée.

AHelps
la source
+1 Cela semble être une solution de contournement très efficace pour Make ne faisant pas nativement les répertoires de sortie de génération par configuration. J'ai une configuration VMware Workstation similaire avec des invités Ubuntu et macOS.
Tanz87
1

Dans un nouveau projet pour moi, j'ai créé une fonctionnalité. Mais certaines spécifications ont échoué. Pour comparer les résultats avec masterj'ai créé un work-treedépôt. J'ai comparé les résultats étape par étape dans le code d'exécution, jusqu'à ce que je comprenne ce qui s'est mal passé.

itsnikolay
la source
Comment un arbre de travail rend-il cela plus facile qu'un clone, cependant? La question n'est pas de demander des préférences personnelles, mais des différences concrètes.
IInspectable
1

J'utilise git worktreepour le développement d'apprentissage automatique.

J'ai un code fonctionnel principal et je veux ensuite diviser les branches de différentes expériences (différents algorithmes et différents hyperparamètres). git worktreeme permet d'intégrer dvc aux côtés de différentes versions de mon code spécialisées dans différents algorithmes. Après avoir exécuté tous les travaux de formation, j'évalue les mesures finales et fusionne pour maîtriser la meilleure branche / le meilleur modèle.

Ricardo MS
la source