Récupérer une propagation spécifique à partir d'un dépôt Git distant

y a-t-il un moyen de récupérer un seul commit spécifique à partir d'un repo Git distant sans le cloner sur mon PC? La structure de Remote repo est absolument la même que la mienne et donc il n'y aura pas de conflits mais je n'ai aucune idée de comment faire cela et je ne veux pas cloner cet énorme dépôt.

, je suis nouveau sur git, est-il de toute façon?

166
demandé sur Daniel 2013-02-14 14:18:07

7 réponses

à partir de la version git 2.5+ (Q2 2015), récupérer une seule commit (sans cloner la pension complète) est en fait possible.

voir commit 68ee628 par Fredrik Medley ( moroten ) , 21 mai 2015.

(fusionné par Junio CA Hamano -- gitster -- dans commit a9d3493 , 01 juin 2015)

vous avez maintenant une nouvelle configuration (côté serveur)

uploadpack.allowReachableSHA1InWant

Autoriser upload-pack pour accepter une demande de récupération qui demande un objet qui est accessible à partir de toutes les ref de la pointe. Toutefois, il est à noter que le calcul de la possibilité d'atteindre un objet coûte cher sur le plan informatique.

Par défaut, false .

si vous combinez cette configuration côté serveur avec un clone peu profond ( git fetch --depth=1 ), vous pouvez demander un seul commit (voir t/t5516-fetch-push.sh :

git fetch --depth=1 ../testrepo/.git $SHA1

vous pouvez utiliser la commande git cat-file pour vérifier que le commit a été trouvé:

git cat-file commit $SHA1

" git upload-pack "qui sert" git fetch " peut être dit de servir s'engage qui ne sont pas à la pointe d'aucun arbitre, tant qu'ils sont accessible à partir d'un ref, avec uploadpack.allowReachableSHA1InWant variable de configuration.


la documentation complète est:

upload-pack "

avec uploadpack.allowReachableSHA1InWant option de configuration définie du côté du serveur, " git fetch "peut faire une requête avec une ligne" want " qui nomme un objet qui n'a pas été annoncé (probablement obtenu hors bande ou à partir d'un pointeur submodule).

Seuls les objets accessibles à partir des pointes de branches, c'est-à-dire l'union des branches annoncées et des branches cachées par transfer.hideRefs , seront traités.

Notez qu'il y a un coût associé à avoir à remonter l'histoire pour vérifier l'accessibilité.

cette fonctionnalité peut être utilisée pour obtenir le contenu d'une certaine commit, pour lequel le sha1 est connu, sans la nécessité de cloner le tout référentiel, surtout si un fetch peu profond est utilisé .

les cas utiles sont par exemple

  • dépôts contenant des fichiers volumineux dans l'histoire,
  • chercher uniquement les données nécessaires pour un sous-module de caisse,
  • en partageant un sha1 sans dire à quelle branche exacte il appartient et dans Gerrit, si vous pensez en termes de commits au lieu de numéros de changement.

    (Le cas Gerrit a déjà été résolu par allowTipSHA1InWant comme chaque changement Gerrit a un réf.)


Git 2.6 (Q3 2015) permettra d'améliorer ce modèle.

Voir commettre 2bc31d1 , commettre cc118a6 (28 Juillet 2015) par Jeff King ( peff ) .

(fusionné par Junio CA Hamano -- gitster -- in commit 824a0be , 19 Aug 2015)

refs : support négatif transfer.hideRefs

si vous cachez une hiérarchie de références en utilisant la config transfer.hideRefs , il n'y a aucun moyen de modifier plus tard cette config pour la" déchiffrer".

Ce patch implémente un cache "négatif" qui fait que les correspondances soient immédiatement marquées comme non-interdites, même si une autre correspond le cacherait.

Nous prenons soin d'appliquer les correspondances dans l'ordre inverse de la façon dont elles nous sont alimentées par la machine de configuration, car cela permet à notre "dernière victoire" habituelle de fonctionner dans la priorité de configuration (et les entrées dans .git/config , par exemple, remplaceront /etc/gitconfig ).

donc vous pouvez maintenant faire:

git config --system transfer.hideRefs refs/secret
git config transfer.hideRefs '!refs/secret/not-so-secret'

à cacher refs/secret dans toutes les prises en pension, à l'exception d'un bit public dans un repo.


Git 2.7 (Nov/Dec 2015) permettra d'améliorer encore:

Voir commettre 948bfa2 , commettre 00b293e (05 Nov 2015), commettre 78a766a , commettre 92cab49 , commettre 92cab49 , commettre 92cab49 (03 Novembre 2015), commettre 00b293e , commettre 00b293e (05 Nov 2015), et commettre 92cab49 , commettre 92cab49 , commettre 92cab49 , commettre 92cab49 (03 Novembre 2015) par Lukas Fleischer ( lfos ) .

Aidé par: Eric Soleil ( sunshineco ) .

(fusionné par Jeff King -- peff -- in commit dbba85e , 20 Nov 2015)

config.txt : document la sémantique de hideRefs avec des espaces de noms

actuellement, il n'y a pas de définition claire de la façon dont transfer.hideRefs devrait se comporter quand un namespace est défini.

Expliquez que hideRefs les préfixes correspondent aux noms dépouillés dans ce cas. C'est comment hideRefs modèles sont actuellement manipulé en pack de réception.

hideRefs: ajout du support pour la mise en correspondance complète refs

en plus des réf strippés correspondants, on peut maintenant ajouter hideRefs motifs contre lesquels le ref complet (non-strippé) est apparié.

Pour distinguer les allumettes dépouillées des allumettes pleines, ces nouveaux motifs doivent être préfixés par un circonflexe. ( ^ ).

D'où le nouvelle documentation :

transfer.hideRefs:

si un espace de noms est utilisé, le préfixe de l'espace de noms est enlevé de chaque référence avant qu'il ne soit apparié avec les motifs transfer.hiderefs .

Par exemple, si refs/heads/master est spécifié dans transfer.hideRefs et l'espace de noms actuel est foo , puis refs/namespaces/foo/refs/heads/master est omise dans le annonces mais refs/heads/master et refs/namespaces/bar/refs/heads/master sont toujours annoncés comme soi-disant "ont" des lignes.

Afin de faire correspondre les valeurs refs avant le stripping, ajouter un ^ devant la ref nom. Si vous combinez ! et ^ , ! doit être indiqué en premier.


R.. mentionne dans les commentaires la config uploadpack.allowAnySHA1InWant , ce qui permet à upload-pack d'accepter une requête fetch qui demande n'importe quel objet. (Par défaut à false ).

voir commit f8edeaa (Nov. 2016, Git v2.11.1) par David "novalis" Turner ( novalis ) :

upload-pack : autoriser optionnellement la récupération de tout sha1

il semble un peu idiot de faire un contrôle de responsabilité dans le cas où nous la confiance de l'utilisateur pour accéder à absolument tout dans le référentiel.

Aussi, c'est racé dans un système distribué, peut-être un serveur la publicité d'un arbitre, mais un autre a depuis fait pression sur ce arbitre, et peut-être que les deux requêtes HTTP finissent par être dirigées vers ces différentes serveur.

87
répondu VonC 2018-07-25 10:50:15

vous ne clonez qu'une seule fois, donc si vous avez déjà un clone du dépôt distant, vous ne pourrez plus Tout télécharger. Il suffit d'indiquer quelle branche vous voulez tirer, ou récupérez les changements et vérifiez la propagation que vous voulez.

récupérer à partir d'un nouveau dépôt est très bon marché dans la bande passante, car il ne téléchargera les changements que vous n'avez pas. Pensez en termes de Git faire la bonne chose, avec un minimum de charge.

Git stocke tout dans le dossier .git . Un commit ne peut pas être récupéré et stocké dans l'isolement, il a besoin de tous ses ancêtres. Ils sont interreliés .


pour réduire la taille du téléchargement, Vous pouvez cependant demander à git de ne récupérer que des objets liés à une branche spécifique ou de commit:

git fetch origin refs/heads/branch:refs/remotes/origin/branch

ceci téléchargera uniquement les propagations contenues dans la branche distante branch (et seulement celles que vous miss) , et le stocker dans origin/branch . Vous pouvez alors fusionner ou acheter.

vous pouvez également spécifier seulement un sha1 commit:

git fetch origin 96de5297df870:refs/remotes/origin/foo-commit

ceci ne téléchargera que le commit de la SHA-1 96de5297df870 spécifiée (et ses ancêtres que vous manquez), et le stockera comme la branche distante (non-existante) origin/foo-commit .

92
répondu CharlesB 2014-06-06 14:46:37

j'ai fait un pull sur mon repo git:

git pull --rebase <repo> <branch>

permettant à git de récupérer tout le code de la branche et ensuite je suis allé faire une réinitialisation à la commit qui m'intéressait.

git reset --hard <commit-hash>

Espérons que cette aide.

58
répondu Piu Sharma 2013-12-03 12:43:17

vous pouvez simplement récupérer un seul commit d'un repo distant avec

git fetch <repo> <commit>

où,

  • <repo> peut être un nom repo distant (par exemple origin ) ou même une URL repo distant (par exemple https://git.foo.com/myrepo.git )
  • <commit> peut être le SHA1 commettre

pour l'exemple

git fetch https://git.foo.com/myrepo.git 0a071603d87e0b89738599c160583a19a6d95545

après avoir récupéré le commit (et les ancêtres disparus) vous pouvez il suffit de vérifier avec

git checkout FETCH_HEAD

notez que cela vous amènera dans l'état de" tête détachée".

42
répondu Flow 2014-06-06 14:50:35

vous pouvez simplement obtenir la prise en charge à distance avec:

git fetch <repo>

où,

  • <repo> peut être un nom repo distant (par exemple origin ) ou même une URL repo distant (par exemple https://git.foo.com/myrepo.git )

par exemple:

git fetch https://git.foo.com/myrepo.git 

après avoir récupéré les repos vous pouvez fusionner les commits que vous voulez (puisque la question Est sur Récupérer une commit, à la place fusionner vous pouvez utilisez le choix de la cerise pour ne choisir qu'une seule commit):

git merge <commit>
  • <commit> peut être le SHA1 commettre

par exemple:

git cherry-pick 0a071603d87e0b89738599c160583a19a6d95545

ou

git merge 0a071603d87e0b89738599c160583a19a6d95545

si c'est la dernière propagation que vous voulez fusionner, vous pouvez aussi utiliser la variable FETCH_HEAD:

git cherry-pick (or merge) FETCH_HEAD
13
répondu Sérgio 2017-06-02 10:43:07

je pense que "git ls-remote" ( http://git-scm.com/docs/git-ls-remote ) devrait faire ce que vous voulez. Sans force, fetch ou pull.

1
répondu Hubbitus 2015-01-28 15:42:04

finalement j'ai trouvé un moyen de cloner la propagation spécifique en utilisant git cherry-pick . En supposant que vous n'avez pas de dépôt en local et que vous retirez la propagation spécifique à distance,

1) Créer un dépôt vide en local et git init

2) git remote add origin url-of-repository

3) git fetch origin [ceci ne déplacera pas vos fichiers vers votre espace de travail local à moins que vous ne fusionniez]

4) git cherry-pick " Entrez au long de la validation de hachage-que-vous-avez-besoin "

fait.De cette façon, vous aurez uniquement les fichiers de commettre dans vos locaux.

Entrez au long de la validation de hachage:

vous pouvez obtenir ceci en utilisant - > git log --pretty = oneline

1
répondu surya deepak 2017-01-03 04:19:49