Comment cloner un sous-répertoire uniquement d’un repository Git?

J’ai mon repository Git qui, à la racine, a deux sous-répertoires:

/finisht /static 

Lorsque ceci était en SVN , /finisht était extrait à un endroit, alors que /static était extrait ailleurs, comme ceci:

 svn co svn+ssh://[email protected]/home/admin/repos/finisht/static static 

Y a-t-il un moyen de faire cela avec Git?

Non, ce n’est pas possible à Git.

Implémenter quelque chose comme ça dans Git serait un effort substantiel et cela signifierait que l’intégrité du repository client ne pourrait plus être garantie. Si cela vous intéresse, recherchez les discussions sur “clone clairsemé” et “fetchsfetch” sur la liste de diffusion git.

En général, le consensus dans la communauté Git est que si vous avez plusieurs répertoires qui sont toujours extraits de manière indépendante, alors ce sont vraiment deux projets différents et devraient vivre dans deux référentiels différents. Vous pouvez les coller ensemble à l’aide de sous-modules Git .

Ce que vous essayez de faire s’appelle une caisse fragmentée , et cette fonctionnalité a été ajoutée dans git 1.7.0 (février 2012). Les étapes pour faire un clone épars sont les suivantes:

 mkdir  cd  git init git remote add -f origin  

Cela crée un référentiel vide avec votre télécommande et récupère tous les objects mais ne les extrait pas. Alors fais:

 git config core.sparseCheckout true 

Vous devez maintenant définir les fichiers / dossiers que vous souhaitez extraire. Cela se fait en les listant dans .git/info/sparse-checkout , par exemple:

 echo "some/dir/" >> .git/info/sparse-checkout echo "another/sub/tree" >> .git/info/sparse-checkout 

Enfin, mettez à jour votre repository vide avec l’état de la télécommande:

 git pull origin master 

Vous allez maintenant avoir des fichiers “extraits” pour some/dir fichiers some/dir et another/sub/tree sur votre système de fichiers (avec ces chemins encore), et aucun autre chemin n’est présent.

Vous voudrez peut-être jeter un coup d’œil au tutoriel étendu et vous devriez probablement lire la documentation officielle pour obtenir un paiement partiel .

En tant que fonction:

 function git_sparse_clone() ( rurl="$1" localdir="$2" && shift 2 mkdir -p "$localdir" cd "$localdir" git init git remote add -f origin "$rurl" git config core.sparseCheckout true # Loops over remaining args for i; do echo "$i" >> .git/info/sparse-checkout done git pull origin master ) 

Usage:

 git_sparse_clone "http://github.com/tj/n" "./local/location" "/bin" 

Notez que cela télécharge toujours l’intégralité du référentiel à partir du serveur – seule la sortie est réduite. Pour le moment, il est impossible de cloner un seul répertoire. Mais si vous n’avez pas besoin de l’historique du référentiel, vous pouvez au moins économiser de la bande passante en créant un clone superficiel. Reportez- vous à la réponse d’udondan ci-dessous pour savoir comment combiner le clone superficiel et la caisse rare.

Vous pouvez combiner la caisse clairsemée et les fonctions de clone peu profondes . Le clone peu profond coupe l’historique et la caisse fragmentée extrait uniquement les fichiers correspondant à vos modèles.

 git init  cd  git remote add origin  git config core.sparsecheckout true echo "finisht/*" >> .git/info/sparse-checkout git pull --depth=1 origin master 

Vous aurez besoin de git 1.9 minimum pour que cela fonctionne. Je l’ai testé seul avec 2.2.0 et 2.2.2.

De cette façon, vous pourrez toujours pousser , ce qui n’est pas possible avec git archive .

Pour les autres utilisateurs qui souhaitent simplement télécharger un fichier / dossier depuis github, utilisez simplement:

 svn export /trunk/ 

par exemple

 svn export https://github.com/lodash/lodash.com/trunk/docs 

(oui, c’est svn ici. Apparemment, en 2016, svn doit simplement télécharger des fichiers github)

Courtoisie: Télécharger un seul dossier ou répertoire depuis un repo GitHub

Important – Assurez-vous de mettre à jour l’URL github et remplacez /tree/master/ par ‘/ trunk /’.

Comme script bash:

 git-download(){ folder=${@/tree\/master/trunk} folder=${folder/blob\/master/trunk} svn export $folder } 

Note Cette méthode télécharge un dossier, ne pas cloner / extraire. Vous ne pouvez pas repasser les modifications dans le référentiel. D’un autre côté, cela se traduit par un téléchargement plus petit par rapport à la caisse clairsemée ou à la caisse peu profonde.

Git 1.7.0 a des «checkouts clairsemés». Voir «core.sparseCheckout» dans la page de manuel git config , «Sparse checkout» dans la page de manuel git read-tree et «Skip-worktree bit» dans la page de manuel git update-index .

L’interface n’est pas aussi pratique que celle de SVN (par exemple, il n’y a aucun moyen d’effectuer une extraction clairs au moment d’un clone initial), mais la fonctionnalité de base sur laquelle des interfaces plus simples pourraient être construites est maintenant disponible.

Si vous ne prévoyez jamais d’interagir avec le référentiel à partir duquel vous avez cloné, vous pouvez faire un clone complet de git et réécrire votre référentiel en utilisant git filter-branch –subdirectory-filter . De cette façon, au moins l’histoire sera préservée.

Cela semble beaucoup plus simple:

 git archive --remote=   | tar xvf - 

Il n’est pas possible de cloner un sous-répertoire uniquement avec Git, mais voici quelques solutions de rechange.

Filtrer la twig

Vous voudrez peut-être réécrire le repository pour qu’il ressemble à trunk/public_html/ avait été sa racine de projet, et ignorer tous les autres historiques (en utilisant filter-branch ), essayez déjà la twig checkout:

 git filter-branch --subdirectory-filter trunk/public_html -- --all 

Remarques: Le -- qui sépare les options de twig de filtre des options de révision, et --all pour réécrire toutes les twigs et les balises. Toutes les informations, y compris les temps de validation originaux ou les informations de fusion, seront conservées . Cette commande honore le .git/info/grafts et les références dans le refs/replace/ namespace, donc si vous avez des greffons ou des refs remplacement définis, l’exécution de cette commande les rendra permanents.

Attention! L’historique réécrit aura des noms d’object différents pour tous les objects et ne convergera pas avec la twig d’origine. Vous ne pourrez pas facilement pousser et dissortingbuer la twig réécrite sur la twig d’origine. S’il vous plaît ne pas utiliser cette commande si vous ne connaissez pas toutes les implications, et évitez de l’utiliser de toute façon, si un simple simple commit suffirait à résoudre votre problème.


Caisse clairsemée

Voici des étapes simples avec une approche d’ extraction fragmentée qui rempliront le répertoire de travail de manière restreinte, de sorte que vous pouvez indiquer à Git quel (s) dossier (s) ou fichier (s) dans le répertoire de travail valent la peine d’être vérifiés.

  1. Cloner le repository comme d’habitude ( --no-checkout est facultatif):

     git clone --no-checkout git@foo/bar.git cd bar 

    Vous pouvez ignorer cette étape si votre référentiel est déjà cloné.

    Indice: pour les --depth 1 importantes, considérez le clone superficiel ( --depth 1 ) pour --depth 1 uniquement la dernière révision ou / et --single-branch seulement.

  2. Activer l’option sparseCheckout :

     git config core.sparseCheckout true 
  3. Spécifiez le (s) dossier (s) pour l’extraction fragmentée ( sans espace à la fin):

     echo "trunk/public_html/*"> .git/info/sparse-checkout 

    ou éditez .git/info/sparse-checkout .

  4. Commander la twig (par ex. master ):

     git checkout master 

Vous devez maintenant avoir des dossiers sélectionnés dans votre répertoire actuel.

Vous pouvez envisager des liens symboliques si vous avez trop de niveaux de répertoires ou de twigs de filtrage.


Je viens d’ écrire un script pour GitHub .

Usage:

 python get_git_sub_dir.py path/to/sub/dir  

Voici un script shell que j’ai écrit pour le cas d’utilisation d’un sous-répertoire unique

coSubDir.sh

 localRepo=$1 remoteRepo=$2 subDir=$3 # Create local repository for subdirectory checkout, make it hidden to avoid having to drill down to the subfolder mkdir ./.$localRepo cd ./.$localRepo git init git remote add -f origin $remoteRepo git config core.sparseCheckout true # Add the subdirectory of interest to the sparse checkout. echo $subDir >> .git/info/sparse-checkout git pull origin master # Create convenience symlink to the subdirectory of interest cd .. ln -s ./.$localRepo$subDir $localRepo