Aller au contenu

Git Subtree

Comme mentionné sur notre page précédente, Git Submodule est utile dans des cas précis. Pour suivre les dépendances logicielles, de nombreux développeurs préfèrent Git Subtree.

Qu'est-ce que Git Subtree

Git Subtree est une alternative à Git Submodule. Il permet d’imbriquer un dépôt dans un autre sous forme de sous-répertoire. C’est l’une des façons de suivre l’historique des dépendances logicielles. Mais les subtrees ne doivent pas être confondus avec les submodules. Contrairement aux submodules, les subtrees n’ont pas besoin de fichiers .gitmodules ni de gitlinks dans le dépôt. Un subtree est simplement un sous-répertoire dans lequel vous pouvez valider, créer des branches et fusionner avec votre projet.

Pourquoi utiliser Git Subtree

Avantages

  • Pris en charge par Git 1.7.10 et versions ultérieures.
  • Gestion du flux de travail simple.
  • Code du sous-projet disponible une fois le super-projet terminé.
  • Aucune nouvelle connaissance Git requise pour utiliser git subtree.
  • N’ajoute pas de nouveaux fichiers de métadonnées (par exemple, .gitmodules).
  • Permet de modifier le contenu sans copie séparée du dépôt de la dépendance.

Inconvénients

  • Nécessite d’apprendre une nouvelle stratégie de fusion.
  • Processus compliqué pour renvoyer du code en amont vers les sous-projets.
  • Le code du super-projet et du sous-projet est mélangé dans le même dépôt.

Comment utiliser Git Subtrees

Supposons qu’il existe un projet externe et que vous souhaitiez l’ajouter à votre dépôt.

Par exemple, pour ajouter une extension vim dans un dépôt qui stocke votre configuration vim, procédez comme suit :

bash
git subtree add --prefix .vim/bundle/example https://github.com/Example/vim-example.git master --squash

Cela compressera tout l’historique du projet vim-example dans votre dossier .vim/bundle/example, en enregistrant le SHA-1 de master au moment de l’opération pour référence future. Le résultat est constitué des deux commits suivants :

bash
commit 6d7054b3acea64e2e31f4d6fb2e3be12e5865e87
Merge: 87fa91e ef86deb
Author: Ann Smith<[email protected]m>
Date:   Tue Jun 10 13:37:03 2016 +0200
    Merge commit 'fe67ddf158faccff4082d78a25c45d8cd93e8ba8' as '.vim/bundle/example'
commit fe67ddf158faccff4082d78a25c45d8cd93e8ba8
Author: Ann Smith<[email protected]m>
Date:   Tue May 12 13:37:03 2015 +0200
    Squashed '.vim/bundle/example/' content from commit b999b09
    git-subtree-dir: .vim/bundle/example
    git-subtree-split: b999b09cd9d69f359fa5668e81b09dcfde455cca

Pour mettre à jour le sous-dossier vers la dernière version du dépôt enfant, exécutez ce qui suit :

bash
git subtree pull --prefix .vim/bundle/example https://github.com/Example/vim-example.git master --squash

Cependant, git subtree stocke les identifiants de commit du sous-projet et non des références dans les métadonnées. Trouvez le nom symbolique associé à un commit :

bash
git ls-remote https://github.com/Example/vim-example.git | grep <commit-sha>

Remplacez <commit-sha> par le hachage de commit réel.

Rebaser après Git Subtree

Pour rebaser un dépôt contenant des subtrees, utilisez le mode --interactive de git rebase. Vous pouvez supprimer ou compresser les commits de fusion du subtree, puis exécuter git rebase --continue. Notez que la réécriture de l’historique nécessite ensuite de réexécuter git subtree add ou git subtree pull. Gardez à l’esprit que la réécriture de l’historique peut provoquer des conflits de fusion lors du rebase des subtrees, car la structure des commits change.

OPTIONS

-q, --quietSupprime les messages de résultat inutiles sur stderr.
-d, --debugProduit des messages de débogage supplémentaires sur stderr.
-P <prefix>, --prefix=<prefix>Définit le chemin dans le dépôt vers le subtree que vous souhaitez manipuler. C’est obligatoire pour toutes les commandes.
-m <message>, --message=<message>Spécifie <message> comme message de commit pour le commit de fusion. Valide uniquement pour add, merge et pull.

Utiliser Git Subtree sans suivi distant

Ajoutez le git subtree dans un dossier de préfixe spécifié. Utilisez l’option --squash pour conserver tout l’historique du sous-projet dans votre dépôt principal :

bash
git subtree add --prefix .vim/bundle/vim-double-upon https://hostname.org/example/vim-plugins.git master --squash

La commande effectue un fetch et compresse l’historique. Le résultat affiche généralement la progression du fetch, puis la confirmation de l’ajout :

bash
git fetch https://hostname.org/example/vim-plugins.git  master
warning: no common commits
remote: Counting objects: 325, done.
remote: Compressing objects: 100% (145/145), done.
remote: Total 325 (delta 101), reused 313 (delta 89)
Receiving objects: 100% (325/325), 61.47 KiB, done.
Resolving deltas: 100% (110/110), done.
From https://hostname.org/vim-plugins.git
* branch master -> FETCH_HEAD
Added dir '.vim/bundle/vim-double-upon'

Cela crée un commit de fusion en compressant tout l’historique du sous-projet en un seul :

bash
3bca0ad [4 minutes ago] (HEAD, stree) Merge commit 'fa2f5dc4f1b94356bca8a440c786a94f75dc0a45' as '.vim/bundle/vim-double-upon' [John Brown]
fa2f5dc [4 minutes ago] Squashed '.vim/bundle/vim-double-upon/' content from commit 13189ec [John Brown]

Pour mettre à jour le code du plugin depuis le dépôt amont, exécutez git subtree pull :

bash
git subtree pull --prefix .vim/bundle/vim-double-upon https://hostname.org/example/vim-plugins.git master --squash

Pour renvoyer les modifications vers le dépôt amont, extrayez l’historique du subtree à l’aide de git subtree split :

bash
git subtree split --prefix .vim/bundle/vim-double-upon -b split-branch
git push split-branch

Cela crée une nouvelle branche contenant uniquement l’historique du subtree, qui peut ensuite être poussée vers le dépôt amont.

Pour raccourcir les commandes, ajoutez le sous-projet comme dépôt distant.

Ajouter le sous-projet comme dépôt distant

L’ajout comme dépôt distant raccourcit le processus :

bash
git remote add -f vim-double-upon https://hostname.org/example/vim-plugins.git

Ajoutez le subtree :

bash
git subtree add --prefix .vim/bundle/vim-double-upon vim-double-upon master --squash

Mettez à jour le sous-projet comme ceci :

bash
git fetch vim-double-upon master
git subtree pull --prefix .vim/bundle/vim-double-upon vim-double-upon master --squash

Git Subtree est une alternative aux submodules. Alors que les submodules placent un autre projet dans un répertoire et maintiennent la synchronisation avec le dépôt distant, Git Subtree conserve le sous-projet comme un répertoire ordinaire. Renvoyer les modifications vers le dépôt amont nécessite d’utiliser git subtree split pour extraire l’historique du sous-projet, car la synchronisation bidirectionnelle directe n’est pas prise en charge nativement.

Practice

What are the features and usage of Git subtree?

Trouvez-vous cela utile?

Aperçu dual-run — comparez avec les routes Symfony en production.