web-dev-qa-db-fra.com

Comment git récupérer efficacement à partir d'un clone peu profond

Nous utilisons git pour distribuer un système d'exploitation et le garder à jour . Nous ne pouvons pas distribuer le référentiel complet car il est trop grand (> 2 Go), nous avons donc utilisé des clones peu profonds (~ 300M). Cependant récemment lors de la récupération à partir d'un clone peu profond, il récupère désormais de manière inefficace l'intégralité du référentiel> 2 Go . Il s'agit d'un gaspillage intenable de bande passante pour les déploiements.

La documentation de git indique que vous ne pouvez pas récupérer à partir d'un référentiel peu profond, bien que ce ne soit strictement pas vrai. Existe-t-il des solutions de contournement pour faire un git clone --depth 1 capable de récupérer ce qui a changé? Ou une autre stratégie pour garder la taille de distribution aussi petite que possible tout en ayant tous les bits dont git a besoin pour faire une mise à jour?

J'ai essayé en vain de cloner à partir de --depth 20 pour voir si la mise à niveau sera plus efficace, cela n'a pas fonctionné. J'ai également examiné http://git-scm.com/docs/git-bundle , mais cela semble créer d'énormes bundles.

44
hendry

--depth Est une option git fetch. Je vois que le document ne met pas vraiment en évidence que git clone Fait une extraction.

Lorsque vous récupérez, les deux référentiels échangent des informations sur qui a quoi en commençant à partir de la tête de la télécommande et en recherchant en arrière la plus récente validation partagée dans les historiques des références récupérées, puis en remplissant tous les objets manquants pour terminer uniquement les nouvelles validations entre le les commits partagés les plus récents et les nouveaux récupérés.

Une extraction --depth=1 Ne donne que les conseils de branchement et aucun historique antérieur. D'autres récupérations de ces historiques récupéreront tout ce qui est nouveau par la procédure ci-dessus, mais si les validations précédemment récupérées ne sont pas dans l'historique nouvellement récupéré, la récupération les récupérera toutes - à moins que vous ne limitiez la récupération avec --depth .

Votre client a effectué une extraction de profondeur = 1 d'un référentiel et a changé d'URL vers un autre référentiel. Au moins un long chemin d'ascendance dans les références de ce nouveau référentiel ne partage apparemment aucun engagement avec quoi que ce soit actuellement dans votre référentiel. Cela peut valoir la peine d'être étudié, mais dans tous les cas, à moins qu'il n'y ait une raison particulière, vos clients peuvent simplement faire chaque extraction --depth=1.

37
jthill

Juste fait g clone github.com:torvalds/linux et ça a pris tellement de temps, donc je l'ai juste sauté par CTRL+C.

Puis g clone github.com:torvalds/linux --depth 1 et il a cloné assez rapidement. Et je n'ai qu'un seul commit dans git log.

Alors clone --depth 1 devrait marcher. Si vous devez mettre à jour le référentiel existant, vous devez utiliser git fetch Origin branchname:branchname --depth 1. Cela fonctionne aussi, il ne récupère qu'un seul commit.

Résumant:

Clone initial:

git clone git_url --depth 1

Mise à jour du code

git fetch Origin branch:branch --depth 1
26
Waterlink

Notez que Git 1.9/2.0 (Q1 2014) pourrait être plus efficace dans la récupération d'un clone peu profond.
Voir commit 82fba2b , de Nguyễn Thái Ngọc Duy (pclouds) :

Maintenant que git prend en charge le transfert de données depuis ou vers un clone peu profond, ces limitations ne sont plus vraies.

Tous les détails sont dans " shallow.c: les 8 étapes pour sélectionner de nouveaux commits pour .git/shallow ".

Vous pouvez voir la conséquence dans des commits comme d7d285 , f2c681c , et c29a7b8 qui supportent le clone, send-pack/receive-pack avec/from shallow clones.
smart-http prend désormais également en charge la récupération/clonage superficiel .
Vous pouvez même un clone forme un dépôt superficiel .

Mise à jour 2015: git 2.5+ (Q2 2015) permettra même une récupération de commit unique ! Voir " Extraire un commit spécifique d'un dépôt git distant ".

Mise à jour 2016 (octobre): git 2.11+ (Q4 2016) permet de récupérer:

11
VonC

Si vous pouvez sélectionner une branche spécifique, cela peut être encore plus rapide. Voici un exemple utilisant Spark branche principale et dernière balise:

Clone initial

git clone [email protected]:Apache/spark.git --branch master --single-branch --depth 1

mise à jour vers une balise spécifique

git fetch --depth 1 Origin tags/v1.6.0

Il devient très rapide de changer de balise/branche de cette façon.

9
Martin Tapp

Je ne sais pas si cela correspond à votre configuration, mais ce que j'utilise, c'est d'avoir un clone complet d'un dépôt dans un répertoire séparé. Ensuite, je fais un clone superficiel à partir du référentiel distant en référence au local.

git clone --depth 1 --reference /path/to/local/clone [email protected]/group/repo.git 

De cette façon, seules les différences avec le référentiel de référence et distant sont réellement récupérées. Pour le rendre encore plus rapide, vous pouvez utiliser le --shared option, mais assurez-vous de lire les restrictions dans la documentation git (cela peut être dangereux).

J'ai également découvert que dans certaines circonstances, lorsque la télécommande a beaucoup changé, le clone commence à récupérer trop de données. Il est alors bon de le casser et de mettre à jour le référentiel de référence (qui prend étrangement beaucoup moins de bande passante qu'il ne le fallait en premier lieu.) Et puis redémarrez le clone.

1
Rajish