web-dev-qa-db-fra.com

Avoir du mal à comprendre git-fetch

J'ai du mal à comprendre les nuances de git-fetch. Je comprends que faire un fetch, récupère les références distantes dans une branche de suivi locale.

J'ai quelques questions cependant:

  1. Est-il possible qu'une branche de suivi locale n'existe pas? Si oui, sera-t-il alors créé automatiquement?

  2. Que se passera-t-il si je fais un fetch et que je spécifie une branche sans suivi comme destination?

  3. La page de manuel de git-fetch spécifie:

    git-fetch <options> <repository> <refspec>
    

Comment utiliser la refspec pour récupérer le contenu de mon maître distant dans sa branche de suivi à distance? Je crois que cela peut être possible si mon actuel HEAD est sur le maître et je lance

git fetch Origin master

Cependant, puis-je utiliser le <+?src:dest> refspec pour réaliser la même chose? Je pense que cela m'aidera à mieux comprendre les concepts.

Et encore une question:

Mon fichier .git/config a la ligne suivante pour la récupération (affichant uniquement les lignes pertinentes):

fetch = +refs/heads/*:refs/remotes/Origin/*

Quelqu'un peut-il expliquer ce que signifie exactement cette ligne?

52
Parag

Tout d'abord, il n'y a pas un tel concept de suivi local branches, seulement suivi à distance branches. Ainsi Origin/master est une branche de suivi à distance pour master dans le repo Origin.

Généralement, vous faites git fetch $ remote qui met à jour toutes vos branches de suivi à distance et en crée de nouvelles si nécessaire.

Cependant, vous pouvez également spécifier une spécification de référence, mais cela ne touchera pas vos branches de suivi à distance, mais récupérera la branche que vous avez spécifiée et l'enregistrera sur FETCH_HEAD, sauf si vous spécifiez une destination. En général, vous ne voulez pas jouer avec ça.

Finalement,

fetch = +refs/heads/*:refs/remotes/Origin/*

Cela signifie que si vous le faites

git fetch Origin

Il fera en fait:

git fetch Origin +refs/heads/*:refs/remotes/Origin/*

Ce qui signifie qu'une télécommande heads/foobar sera locale remotes/Origin/foobar, et le signe plus signifie qu'ils seront mis à jour même s'ils ne sont pas en avance rapide.

Peut-être que ce que vous pensez en tant que branche de suivi est lié à git pull et à la configuration de fusion.

59
FelipeC

felipec ont répondu à la plupart des problèmes en question dans sa réponse .

Quelques-uns restants (la plupart proviennent de git fetch page de manuel; qui est un peu daté à certains endroits, malheureusement):

  • Si branche de suivi à distance (branche qui suit une branche dans un référentiel distant) n'existe pas, elle serait créée.

  • La branche dans laquelle vous allez chercher (le <dst> dans [+]<src>:<dst>) n'a pas besoin de résider dans remotes/<remote>/ espace de noms. Par exemple, pour mettre en miroir des référentiels (git clone --mirror) refspec est de 1 à 1. Autrefois, avant la disposition des télécommandes séparées (avant remotes/<remote>/ espace de noms pour les références de suivi à distance) master la branche a été récupérée dans la branche appelée Origin. Même actuellement, les balises sont récupérées directement dans tags/ espace de noms en miroir.

  • Si la branche dans laquelle vous allez chercher (le côté droit de refspec <src>:<dst> existe, Git vérifierait si le téléchargement entraînerait une avance rapide, c'est-à-dire si l'état actuel dans <dst> est l'ancêtre de l'État dans <src> dans un référentiel distant donné. Si ce n'est pas le cas et que vous n'utilisez pas -f/--force option pour git-fetch, ou préfixer refspec avec '+' (utilisez +<src>:<dst> refspec) fetch refuserait de mettre à jour cette branche.

  • git fetch Origin master est équivalent à git fetch Origin master:, pas à git fetch Origin master:master; il stocke la valeur extraite de master branche (de remote Origin) dans FETCH_HEAD, et non dans master branche ou suivi à distance remotes/Origin/master branche. Il peut être suivi de git merge FETCH_HEAD. Généralement non utilisé directement, mais dans le cadre d'une extraction ponctuelle sans définir de branche de suivi à distance: git pull <URL> <branch>.

  • +refs/heads/*:refs/remotes/Origin/* comme valeur pour remote.Origin.fetch variable de configuration signifie que chaque branche (ref dans refs/heads/ namespace) dans remote Origin est récupéré dans la branche de suivi à distance nommée respectivement dans refs/remotes/Origin/ espace de noms, par exemple master branche dans Origin (c'est-à-dire refs/heads/master ref) serait récupéré dans Origin/master branche de suivi à distance (c'est-à-dire refs/remotes/Origin/master réf). Le préfixe "+" signifie que l'extraction réussirait même dans le cas d'une avance rapide, ce qui signifie que la branche sur la télécommande est rebasée, ou rembobinée (réinitialisée dans un état antérieur) ou autrement modifiée.

Sidenote: Vous voudrez probablement utiliser un niveau supérieur git remote commande pour gérer la télécommande référentiels et obtenir des mises à jour.

23
Jakub Narębski

Notez que le principal responsable de Git a maintenant (Git 2.1, août 2014) ajouté cette explication pour git fetch :
(Voir commit fcb14b par Junio ​​C Hamano (gitster) :

BRANCHES DE SUIVI À DISTANCE CONFIGURÉES

Vous interagissez souvent avec le même référentiel distant en le récupérant régulièrement et à plusieurs reprises. Afin de suivre la progression d'un tel référentiel distant, git fetch vous permet de configurer remote.<repository>.fetch variables de configuration.

Typiquement, une telle variable peut ressembler à ceci:

[remote "Origin"]
fetch = +refs/heads/*:refs/remotes/Origin/*

Cette configuration est utilisée de deux manières:

  • Quand git fetch est exécuté sans spécifier les branches et/ou balises à récupérer sur la ligne de commande, par exemple git fetch Origin ou git fetch, remote.<repository>.fetch les valeurs sont utilisées comme refspecs --- elles spécifient les références à extraire et les références locales à mettre à jour .
    L'exemple ci-dessus va récupérer toutes les branches qui existent dans le Origin (c'est-à-dire toute référence qui correspond au côté gauche de la valeur, refs/heads/*) et mettez à jour les branches de suivi à distance correspondantes dans le refs/remotes/Origin/* hiérarchie.

  • Quand git fetch est exécuté avec des branches et/ou des balises explicites à récupérer sur la ligne de commande, par exemple git fetch Origin master, les <refspec>s donnés sur la ligne de commande déterminent ce qui doit être récupéré (par exemple master dans l'exemple, qui est un raccourci pour master:, ce qui signifie à son tour "récupérer la branche 'master' mais je ne dis pas explicitement quelle branche de suivi à distance mettre à jour avec elle depuis la ligne de commande"), et l'exemple de commande récupérera only la branche 'master'.
    Le remote.<repository>.fetch les valeurs déterminent la branche de suivi à distance, le cas échéant, qui est mise à jour.
    Lorsqu'il est utilisé de cette manière, le remote.<repository>.fetch les valeurs n'ont aucun effet pour décider quoi est récupéré (c'est-à-dire que les valeurs ne sont pas utilisées comme refspecs lorsque la ligne de commande répertorie les refspecs); ils ne sont utilisés que pour décider les références qui sont récupérées sont stockées en agissant comme un mappage.

4
VonC

Notez également que, avec Git 2.5+ (Q2 2015), git merge FETCH_HEAD peut fusionner plusieurs git fetch's .

Voir commit d45366e by Junio ​​C Hamano (gitster) , 26 mars 2015.
(Fusionné par Junio ​​C Hamano - gitster - in commit bcd1ecd , 19 mai 2015)

"git merge FETCH_HEAD "a appris que le précédent" git fetch "pourrait être de créer une fusion Octopus, c'est-à-dire d'enregistrer plusieurs branches qui ne sont pas marquées comme" pas pour la fusion ";
cela nous permet de perdre une ancienne invocation de style "git merge <msg> HEAD $commits... "dans l'implémentation de" git pull "script; l'ancienne syntaxe de style peut désormais être déconseillée.

Le git merge doc mentionne maintenant:

Quand FETCH_HEAD (et aucun autre commit) n'est spécifié, les branches enregistrées dans le .git/FETCH_HEAD fichier par l'invocation précédente de git fetch pour la fusion sont fusionnés avec la branche courante .


Git 2.13 (Q2 2017) retire officiellement l'ancienne syntaxe pour git merge.
Voir commit b439165 (26 mars 2015) par Junio ​​C Hamano (gitster) .
(Fusionné par Junio ​​C Hamano - gitster - in commit 1fdbfc4 , 30 mars 2017)

merge: drop 'git merge <message> HEAD <commit> 'syntaxe

Arrêtez de prendre en charge "git merge <message> HEAD <commit> "syntaxe déconseillée depuis octobre 2007 et émet un message d'avertissement de dépréciation depuis la v2.5.0.

Cela signifie que le message d'avertissement à l'ancienne "'git merge <msg> HEAD <commit>' is deprecated." n'est plus.

2
VonC