web-dev-qa-db-fra.com

Caisse clairsemée dans Git 1.7.0?

Avec la nouvelle fonctionnalité sparse checkout dans Git 1.7.0, est-il possible d’obtenir le contenu d’un sous-répertoire comme vous le feriez dans SVN? J'ai trouvé cet exemple , mais il conserve la structure de répertoires complète. Imaginez que je voulais juste le contenu du répertoire 'Perl', sans répertoire réel nommé 'Perl'.

-- MODIFIER --

Exemple:

Mon référentiel git contient les chemins suivants

repo/.git/
repo/Perl/
repo/Perl/script1.pl
repo/Perl/script2.pl
repo/images/
repo/images/image1.jpg
repo/images/image2.jpg
repo/doc/
repo/doc/readme.txt
repo/doc/help.txt

Ce que je veux, c'est pouvoir produire à partir du référentiel ci-dessus cette présentation:

repo/.git/
repo/script1.pl
repo/script2.pl

Cependant, avec la fonctionnalité de paiement fragmenté actuelle, il semble qu’il est seulement possible d’obtenir

repo/.git/
repo/Perl/script1.pl
repo/Perl/script2.pl

ce qui n'est pas ce que je veux.

67
davr

Vous devez toujours cloner le référentiel entier, qui contiendra tous les fichiers. Vous pouvez utiliser l'indicateur --depth pour ne récupérer qu'une quantité limitée d'historique.

Une fois le référentiel cloné, l'astuce de lecture vous limite votre "vue" du référentiel aux seuls fichiers ou répertoires contenus dans le fichier .git/info/sparse-checkout.

J'ai écrit un script rapide pour aider à gérer la rareté, car pour le moment, c'est un peu hostile:

#!/bin/sh
echo > .git/info/sparse-checkout
for i in "$@"
do
    echo "$i" >> .git/info/sparse-checkout
done
git read-tree -m -u HEAD

Si vous enregistrez ce script sous le nom git-sparse.sh dans le chemin indiqué en appelant git --exec-path, vous pouvez alors exécuter git sparse foo/ bar/ uniquement pour "extraire" les répertoires foo et bar, ou git sparse '*' pour tout récupérer.

26
richq

La réponse courte est non. Git voit tous les fichiers comme une seule unité.

Ce que je recommande, c’est de diviser les dépôts en blocs logiques. Un fichier distinct pour Perl, les images et la documentation. Si vous souhaitez également conserver le style de repo uber, vous pouvez créer un repo composé de Submodules .

16
John K

la réponse de richq était proche, mais il manquait une étape. Vous devez activer explicitement le paiement clairsemé:

git config core.sparsecheckout true

Ce blog a toutes les étapes décrites clairement:

http://blog.quilitz.de/2010/03/checkout-sub-directories-in-git-sparse-checkouts/comment-page-1/#comment-3146

7
PhilYoussef

Maintenant, sans entrer dans les détails sur pourquoi voudriez-vous faire cela, votre problème peut être (probablement) facilement résolu par un lien symbolique/un raccourci.

Pour répondre à la question - non, et avec une raison valable. Toute l’historique du repo est téléchargée même avec un «paiement clairsemé». Pour clarifier pourquoi cela est nécessaire - sinon, suivre les fichiers renommés serait un problème pour ... le cou. Imaginez que vous déplacez le fichier /repo_root/asd/file1.cpp vers /repo_root/fgh/file1.cpp - maintenant, si vous n'aviez téléchargé que des deltas /repo_root/fgh, vous ne saurez rien sur file1.cpp. Cela signifie donc que vous devez télécharger tous les deltas. Mais alors vous avez un référentiel complet; pas seulement un dossier coupé, donc le dossier /rero_root/fgh n’est pas un repo en soi. Cela peut ne pas sembler important lorsque vous passez à la caisse, mais lorsque vous vous engagez, il se peut que git n'en sache pas assez pour fonctionner correctement.

Solution de contournement : Si vous le souhaitez vraiment, vous pouvez créer un script qui appelle git-checkout de cette manière (pour le sh Shell, le traitement par lots pour Windows ne devrait pas être difficile à produire):

!/bin/sh
curDir=`pwd`
cd $2
git-checkout $1
cp -R $3/* $4
cd $curDir

Ici, le premier argument est la branche à extraire, le second - le dossier dans lequel le référentiel est actuellement présent, le troisième - le sous-répertoire que vous voulez vraiment utiliser et le quatrième - l'emplacement vers lequel vous souhaitez le copier.

Attention: mes compétences Shell sont quasi inexistantes, utilisez-les après les tests. Il ne devrait pas être difficile de recréer l’inverse du script, qui recopie les éléments, de manière à pouvoir les enregistrer dans le référentiel.

5
Ger4ish

git filter-branch --subdirectory-filter est ce dont vous avez besoin, voir le sous-répertoire Detach (move) dans un référentiel Git séparé .

Voici un petit script bash pour le faire.

Cela créera d’abord une copie de travail du référentiel original, puis filtrera la branche en utilisant le filtre de sous-répertoires pour obtenir ce que vous voulez.

#!/bin/bash
#
# git-subdir.sh
#
git clone --no-hardlinks $1 $2

cd $2

git filter-branch --subdirectory-filter $2 --Prune-empty --tag-name-filter cat HEAD -- --all

git reset --hard

git remote rm Origin

refbak=$(git for-each-ref --format="%(refname)" refs/original/)

if [ -n "$refbak" ];then
    echo -n $refbak | xargs -n 1 git update-ref -d
fi

git reflog expire --expire=now --all

git repack -ad

git gc --aggressive --Prune=now

Utilisez pour l'exemple dans la question, git-subdir.sh repo Perl fonctionnerait.

3
weynhamz

Vous pouvez essayer braid - il suit les télécommandes tout en les faisant correspondre à un chemin . https://github.com/evilchelu/braid/wiki

2
Antoine Toulme

Il semble que ce que vous essayez de faire est de renommer l’arborescence de répertoires de sorte que vos fichiers se retrouvent à un emplacement différent. Il me semble que vous demandez un anti-modèle pour la gestion de code/projet sur deux plans: la catégorisation des modules (bits Java sous le noeud Java, Perl sous le noeud Perl) et avoir un projet avec des fichiers situés à différents emplacements d'où le développeur les visualise. Comme git maintient le hachage du contenu du répertoire pour voir ce qui a été changé, cela rompt également git en tant que tel. 

Daemeon Reiydelle

0
Daemeon