L’option reference de git clone
Il existe une option dans git pour cloner un dépôt qui n’est pas très connue mais qui mérite pourtant de l’être d’avantage.
Section intitulée prenons-quelques-cas-d-utilisation-pour-illustrer-cette-optionPrenons quelques cas d’utilisation pour illustrer cette option
Section intitulée le-serveur-de-buildLe serveur de build
Sur un serveur de build ou lors d’un déploiement, vous avez besoin du dépôt git pour construire l’application. Mais ce dépôt ne doit contenir aucun artefact d’un build précédent. En effet, nous ne voulons pas envoyer en prod des fichiers inutiles, ou des fichiers de configuration obsolète. De plus, il faut être capable de builder plusieurs branches en parallèle.
Nous pourrions être tentés d’utiliser la solution suivante, dans un dossier où le repo est déjà sur la machine :
cd /home/build/projectX/
git fetch
git reset --hard <SHA>
git clean -fdx # Supprime tout ce qui n’est pas tracké par git, même ce qui est ignoré
… mais cela ne permettra pas de builder plusieurs branches en parallèle (il faut un dossier par build). De plus, nous ne sommes jamais à l’abri d’un oubli de git clean -fdx
qui pourrait laisser des artefacts d’un build précédent à cause d’un problème de droit (been there!).
Section intitulée en-localEn local
En local, vous voulez tester dans un environnement propre. C’est-à-dire que vous voulez un dépôt nu, sans configuration, etc. Cela peut être utile pour tester des scripts de déploiement, des scripts de build, etc. Ici, vous ne voulez pas supprimer toutes vos configurations, vous pouvez alors faire un git clone
mais cela peut être un peu lent si le dépôt est gros.
Section intitulée la-ciLa CI
Il est possible d’optimiser certaines CI quand les planètes sont alignées. Par exemple, avec GitLab, quand il n’existe qu’un hosted runner. Nous pouvons utiliser le même dossier pour plusieurs jobs. Cela permet de ne pas avoir à cloner le dépôt a chaque job, de télécharger les dépendances une seule fois, etc.
Comme en local, nous pourrions utiliser git clone
, mais cela va induire de la latence sur le premier job de build. Surtout que GitLab a déjà cloné le projet ! Et qu’il n’est pas rare de voir des repository de plusieurs centaines de Mo, voire plusieurs Go.
Section intitulée la-solutionLa solution
La solution est d’utiliser l’option --reference
de git clone
. Celle-ci permet de cloner un dépôt en utilisant un autre dépôt local comme référence. Cela permet de ne pas avoir à télécharger les objets git déjà présents dans le dépôt de référence.
De plus, git va automatiquement le mettre à jour avec les objets manquants. Cela permet de ne pas avoir à gérer sa mise à jour.
Section intitulée exemple-du-serveur-de-buildExemple du serveur de build
Avec le layout suivant :
-
/home/build/projectX/reference.git/
: Dépôt de référence, qui peut même être cloné avec--bare
pour économiser de l’espace disque ; -
/home/build/projectX/build/0001
: Le dépôt nu pour le build 0001 que l’on veut cloner.
Nous allons lancer la commande suivante :
git clone \ #
--reference /home/build/projectX/reference.git/ \ # le dépôt de référence
git@github.com/jolicode/projectX.git \ # la source
/home/build/projectX/build/0001 # la destination
git va alors (retranscription très approximative de la réalité) :
- Mettre à jour le dépôt de référence avec les objets manquants
cd /home/build/projectX/reference.git/ && git fetch
- Cloner le dépôt en utilisant le dépôt de référence
git clone /home/build/projectX/reference.git/ /home/build/projectX/build/0001
- Mettre à jour la configuration du dépôt cloné pour mettre le vrai upstream
tout en gardant le dépôt de référence pour les objets git.cd /home/build/projectX/build/0001 && git remote set-url origin git@github.com/jolicode/projectX.git
Et voilà, vous avez un dépôt cloné très rapidement, sans aucun artefact précédent et qui est prêt à être utilisé pour un build.
Le clone a été très rapide car il n’a pas été nécessaire de télécharger depuis le git distant les objets déjà présents dans le dépôt de référence. Ce n’est qu’une copie locale des objets déjà présents.
Nous pouvons même aller encore plus loin pour optimiser le clone lors d’un build :
git clone \ #
--reference /home/build/projectX/reference.git/ \ # le dépôt de référence
--depth 1 \ # seulement le dernier commit
--branch prod \ # de la branch prod
git@github.com/jolicode/projectX.git \ # la source
/home/build/projectX/build/0001 # la destination
Avec cette commande, vous n’avez que le dernier commit de la branche prod. Pas besoin de gérer des git fetch / git reset / git checkout, git le fait pour vous en une commande !
Section intitulée exemple-pour-la-ciExemple pour la CI
Les moteurs d’intégration continue clonent déjà le dépôt pour vous. Vous pouvez alors utiliser le dépôt cloné comme référence pour les autres jobs. Cependant, ils utilisent déjà l’option --depth 1
pour ne cloner que le dernier commit. Il vous faudra alors utiliser l’option unshallow
pour que le dépôt cloné soit complété avec tous les objets git du projet.
git fetch --unshallow
Vous n’aurez ensuite plus qu’à utiliser la commande qu’on a vue plus haut 🎉
Utiliser cette technique vous fera gagner du temps et de la bande passante, il serait dommage de s’en passer. Joyeux clonage !
Commentaires et discussions
Nos formations sur ce sujet
Notre expertise est aussi disponible sous forme de formations professionnelles !
Git
Historisez vos développements avec l’outil de gestion de version Git