Si vous développez depuis plus de trois mois, vous vous êtes sûrement déjà dit « j’aimerai bien factoriser ce petit bout de code pour l’utiliser dans d’autres projets ». Si vous travaillez avec Git, la solution la plus simple est de créer un nouveau dépôt Git et d’y copier le dossier qui vous intéresse. Cela a un gros désavantage : vous perdez tout l’historique du dossier. Si le projet a déjà quelques mois, il est fort à parier que des informations importantes se trouvent dans cet historique (vous écrivez de bon messages de commits, n’est-ce pas ?).

Diviser pour régner

Il est heureusement possible de créer un nouveau dépôt git pour un sous-dossier de votre projet tout en conservant son historique. « Quelle est cette magie !? » me dites-vous ? La réponse est git subtree.

git-2.png

git subtree va vous permettre de créer un nouvel arbre de commits pour un sous-dossier de votre dépôt git. Autrement dit, git subtree regénère l’historique d’un dossier.

En pratique, qu’est-ce que cela donne ?

git subtree split -P my-dir -b my-dir-branch

Cette commande va générer un arbre de commits à partir de celui existant, uniquement pour le répertoire _my-dir _et va le stocker sur la branche my-dir-branch. Si vous faite un git checkout my-dir-branch, votre worktree va complètement changer pour se transformer en votre sous-dossier.

En réalité, vous voulez sans doute pousser ce nouvel historique ailleurs :

git subtree push -P my-dir git@mon-serveur-git:group/projet.git master

Cette commande va également créer le nouvel historique mais va cette fois le pousser sur la branche _master_ du dépôt mon-serveur-git:group/projet.git.

Bonus

  • Des sous-commandes existent également pour réintégrer un historique dans un sous-dossier (fonctionnalité relativement proche des git submodules) : git subtree addgit subtree pull et git subtree merge.
  • Techniquement, git crée de nouveaux commits : ils ont les mêmes meta-données (message, date, auteur, etc.), mais ne sont qu’une sous partie des commits originaux : ils n’ont pas les mêmes commits parents et les patchs qu’ils portent peuvent être différents. C’est pour cela qu’ils ont des IDs différents et qu’ils ne sont pas intégrés à l’arbre initial. Le résultat, c’est que dans un même dépôt git, vous allez avoir plusieurs arbres de commits qui n’ont potentiellement aucun commit en commun (sauf si vous avez fait un git subtree merge/add/pull) et pas le même commit inital, c’est comme si vous aviez plusieurs dépôts git en un.
  • La fonctionnalié git subtree n’est disponible que depuis git 1.7.11. Si vous êtes sous Debian Wheezy, il vous faudra utiliser les backports (Wheezy utilise git 1.7.10)..

Auteur : Theo Chamley