web-dev-qa-db-fra.com

Récupérer une validation spécifique à partir d'un référentiel Git distant

Est-il possible de récupérer un seul commit spécifique à partir d'un dépôt Git distant sans le cloner sur mon PC? La structure de repo à distance est absolument identique à celle de la mienne et par conséquent, il n'y aura pas de conflits, mais je ne sais pas comment faire cela et je ne veux pas cloner cet énorme référentiel.

Je suis nouveau à git, y at-il un moyen?

178
Varun Chitre

À partir de la version 2.5 + de Git (T2 2015), il est en fait possible d'extraire un seul commit (sans cloner le référentiel complet).

Voir commit 68ee628 par Fredrik Medley (moroten) , 21 mai 2015.
(Fusionné par Junio ​​C Hamano - gitster - dans commit a9d349 , 01 juin 2015)

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

_uploadpack.allowReachableSHA1InWant
_

Autoriser _upload-pack_ à accepter une demande d'extraction demandant un objet accessible à partir de toute info-bulle. Cependant, notez que le calcul de l'accessibilité aux objets est coûteux en calcul.
La valeur par défaut est 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 voir que la validation a été extraite:

_git cat-file commit $SHA1
_

"_git upload-pack_" qui sert "_git fetch_" peut servir à exécuter des commits qui ne se trouvent pas à l'extrémité d'un ref, tant qu'ils sont accessibles à partir d'une référence, avec la variable de configuration _uploadpack.allowReachableSHA1InWant_ .


La documentation complète est:

_upload-pack_: autoriser éventuellement l'extraction accessible sha1

Lorsque l'option de configuration _uploadpack.allowReachableSHA1InWant_ est définie côté serveur, "_git fetch_" peut faire une demande avec une ligne "vouloir" qui nomme un objet qui n'a pas été annoncé (probablement d'avoir été obtenu hors bande ou d'un pointeur de sous-module).
Seuls les objets accessibles à partir des conseils de branche, c’est-à-dire l’union des branches annoncées et des branches cachées par _transfer.hideRefs_, seront traités.
Notez qu’il ya un coût associé à la nécessité de parcourir l’historique pour vérifier l’accessibilité.

Cette fonctionnalité peut être utilisée pour obtenir le contenu d'un certain commit pour lequel le sha1 est connu, sans qu'il soit nécessaire de cloner l'ensemble du référentiel, en particulier si une extraction superficielle est utilisée .

Les cas utiles sont, par exemple,.

  • des référentiels contenant des fichiers volumineux dans l'historique,
  • ne récupérant que les données nécessaires à une extraction de sous-module,
  • lorsque vous partagez un sha1 sans préciser à quelle branche il appartient et dans Gerrit, si vous pensez en termes de commits au lieu de changer de numéro.
    (L’affaire Gerrit a déjà été résolue par le biais de _allowTipSHA1InWant_, chaque changement de Gerrit ayant un réf.)

Git 2.6 (Q3 2015) améliorera ce modèle.
Voir commit 2bc31d1 , commit cc118a6 (28 juil. 2015) par Jeff King (peff) .
(Fusion par Junio ​​C Hamano - gitster - dans commit 824a0be , 19 août 2015)

refs: support négatif _transfer.hideRefs_

Si vous masquez une hiérarchie de références à l'aide de la configuration _transfer.hideRefs_, il n'existe aucun moyen de remplacer ultérieurement cette configuration pour la "révéler".
Ce patch implémente un masquage "négatif" qui permet de marquer immédiatement les correspondances comme non masquées, même si une autre correspondance les masquerait.
Nous prenons soin d’appliquer les allumettes dans l’ordre inverse de la façon dont elles nous sont fournies par la machine de configuration, afin que notre "dernier gagnant" gagne le travail de priorité de la configuration (et les entrées dans _.git/config_ , par exemple, remplacera _/etc/gitconfig_).

Alors vous pouvez maintenant faire:

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

masquer _refs/secret_ dans tous les dépôts, à l'exception d'un bit public dans un dépôt spécifique.


Git 2.7 (nov/déc 2015) va encore s'améliorer:

Voir commit 948bfa2 , commit 00b293e (05 nov. 2015), commit 78a766a , commit 92cab49 , commit 92cab49 , commit 92cab49 (03 nov. 2015), commit 00b293e , commit 00b293e (05 nov 2015), et commit 92cab49 , commit 92cab49 , commit 92cab49 , commit 92cab49 (03 nov. 2015) par Lukas Fleischer (lfos) .
Aidé par: Eric Sunshine (sunshineco) .
(Fusionnée par Jeff King - peff - dans commit dbba85e , 20 nov. 2015)

_config.txt_: documenter la sémantique de hideRefs avec des espaces de noms

À l'heure actuelle, il n'existe pas de définition claire du comportement de _transfer.hideRefs_ lorsqu'un espace de nommage est défini.
Expliquez que hideRefs les préfixes correspondent aux noms supprimés dans ce cas. C'est ainsi que les modèles hideRefs sont actuellement traités dans receive-pack.

hideRefs: ajout du support pour faire correspondre les références complètes

En plus de faire correspondre les références supprimées, vous pouvez maintenant ajouter hideRefs motifs auxquels la référence complète (non séparée) correspond.
Pour distinguer les matchs dénudés des matchs complets, ces nouveaux modèles doivent être précédés d’un circumflexe (_^_).

D'où le nouvelle documentation :

_transfer.hideRefs:
_

Si un espace de noms est en cours d'utilisation, le préfixe d'espace de noms est supprimé de chaque référence avant d'être mis en correspondance avec les modèles _transfer.hiderefs_.
Par exemple, si _refs/heads/master_ est spécifié dans _transfer.hideRefs_ et que l’espace de nommage actuel est foo, alors _refs/namespaces/foo/refs/heads/master_ est omis des publications mais _refs/heads/master_. et _refs/namespaces/bar/refs/heads/master_ sont toujours annoncés sous la forme de lignes dites "avoir".
Afin de faire correspondre les références avant de supprimer, ajoutez un _^_ devant le nom de la référence. Si vous combinez _!_ et _^_, _!_ doit être spécifié en premier.


R .. mentionne dans les commentaires la configuration uploadpack.allowAnySHA1InWant , ce qui permet à _upload-pack_ d'accepter un fetch demande qui demande n'importe quel objet. (La valeur par défaut est false).

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

_upload-pack_: autoriser éventuellement la récupération de sha1

Il semble un peu idiot de faire une vérification de la vulnérabilité dans le cas où nous faisons confiance à l'utilisateur pour accéder à tout ce qui se trouve dans le référentiel.

En outre, il est racé dans un système distribué: un serveur peut annoncer une référence, mais un autre a depuis été forcé de s'exercer sur cette référence et les deux requêtes HTTP doivent être redirigées vers ces différents serveurs.

103
VonC

Vous ne clonez qu'une seule fois. Par conséquent, si vous avez déjà un clone du référentiel distant, son extraction ne téléchargera pas tout à nouveau. Indiquez simplement quelle branche vous souhaitez extraire, ou récupérez les modifications et extrayez le commit que vous souhaitez.

La récupération depuis un nouveau référentiel est très économique en bande passante, car elle ne téléchargera que les modifications que vous n'avez pas. Pensez en termes de Git faisant la bonne chose, avec une charge minimale.

Git stocke tout dans le dossier .git. Un commit ne peut pas être récupéré et stocké isolément, il a besoin de tous ses ancêtres. Ils sont interdépendants .


Pour réduire la taille du téléchargement, vous pouvez cependant demander à git de ne récupérer que les objets liés à une branche ou à une validation spécifique:

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

Cela téléchargera uniquement les commits contenus dans la branche distante branch(et seulement ceux qui vous manquent), et enregistrez-le dans Origin/branch. Vous pouvez ensuite fusionner ou passer à la caisse.

Vous pouvez également spécifier uniquement un commit SHA1:

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

Cela téléchargera uniquement le commit du SHA-1 96de5297df870 spécifié (et de ses ancêtres manquants), et le stockera en tant que branche distante (non existante) Origin/foo-commit.

94
CharlesB

J'ai tiré sur mon dépôt Git:

git pull --rebase <repo> <branch>

Permettre à Git de récupérer tout le code de la branche puis d’aller réinitialiser le commit qui m’intéressait.

git reset --hard <commit-hash>

J'espère que cela t'aides.

60
Piu Sharma

Vous pouvez simplement extraire un seul commit d'un dépôt distant avec

git fetch <repo> <commit>

où,

  • <repo> peut être un nom de dépôt distant (par exemple, Origin) ou même une URL de dépôt distant (par exemple, https://git.foo.com/myrepo.git).
  • <commit> peut être le commit SHA1

par exemple

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

une fois que vous avez récupéré le commit (et les ancêtres manquants), vous pouvez simplement le vérifier avec

git checkout FETCH_HEAD

Notez que cela vous amènera à l'état "tête détachée".

46
Flow

Vous pouvez simplement aller chercher le dépôt distant avec:

git fetch <repo>

où,

  • <repo> peut être un nom de dépôt distant (par exemple, Origin) ou même une URL de dépôt distant (par exemple, https://git.foo.com/myrepo.git).

par exemple:

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

une fois que vous avez récupéré le dépôt, vous pouvez fusionner les commits que vous souhaitez (étant donné que la question concerne l'extraction d'un commit, vous pouvez utiliser la sélection par choix pour sélectionner un seul commit):

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

par exemple:

git cherry-pick 0a071603d87e0b89738599c160583a19a6d95545

ou

git merge 0a071603d87e0b89738599c160583a19a6d95545

si vous souhaitez fusionner avec la dernière validation, vous pouvez également utiliser la variable FETCH_HEAD:

git cherry-pick (or merge) FETCH_HEAD
16
Sérgio

Cela fonctionne mieux:

git fetch Origin specific_commit
git checkout -b temp FETCH_HEAD

nommez "temp" comme vous voulez ... cette branche pourrait être orpheline

1
Alexander Mills

Enfin, j'ai trouvé un moyen de cloner un commit spécifique en utilisant git cherry-pick. En supposant que vous n’ayez aucun référentiel en local et que vous extrayiez un commit spécifique à distance,

1) créer un référentiel 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 dans votre espace de travail local à moins que vous ne fusionniez]

4) git cherry-pick " Entrez-longue-validation-hachage que vous ayez besoin "

Fait. De cette façon, vous aurez uniquement les fichiers de ce commit spécifique dans votre section locale.

Enter-long-commit-hash:

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

1
surya deepak

Je pense que 'git ls-remote' ( http://git-scm.com/docs/git-ls-remote ) devrait faire ce que vous voulez. Sans forcer chercher ou tirer.

0
Hubbitus

Si la validation demandée se trouve dans les demandes d'extraction du référentiel distant, vous pouvez l'obtenir par son ID:

# Add the remote repo path, let's call it 'upstream':
git remote add upstream https://github.com/repo/project.git

# checkout the pull ID, for example ID '60':
git fetch upstream pull/60/head && git checkout FETCH_HEAD
0
Noam Manos