Est-ce que «git fetch --tags» inclut «git fetch»?

270

Une question agréable et simple - la fonction de "git fetch" est-elle un sous-ensemble strict de git fetch --tags?

C'est-à-dire si je cours git fetch --tags, y a-t-il jamais une raison de courir git fetchimmédiatement après?

Et pour git pullet git pull --tags? Même situation?

davidA
la source
11
À partir de Git 1..9 / 2.0 (T1 2014), la réponse sera oui . Voir ma réponse ci
VonC
3
Pour l'éditeur qui a "corrigé mon texte" avec une modification - on ne met pas nécessairement en majuscule après un trait d'union ou un acronyme, donc votre modification était grammaticalement incorrecte, c'est pourquoi je l'ai rejetée.
davidA

Réponses:

177

Remarque: à partir de git 1.9 / 2.0 (Q1 2014) , git fetch --tagsrécupère les balises en plus de celles récupérées par la même ligne de commande sans l'option.

Voir commit c5a84e9 par Michael Haggerty (mhagger) :

Auparavant, l' --tagsoption " " de fetch était considérée comme équivalente à la spécification de la spécification de référence

refs/tags/*:refs/tags/*

sur la ligne de commande; en particulier, il a provoqué l' remote.<name>.refspecignorance de la configuration.

Mais il n'est pas très utile de récupérer des balises sans chercher également d'autres références, alors qu'il est très utile de pouvoir récupérer des balises en plus d' autres références.
Modifiez donc la sémantique de cette option pour faire cette dernière.

Si un utilisateur veut récupérer uniquement des balises, il est toujours possible de spécifier une spécification explicite:

git fetch <remote> 'refs/tags/*:refs/tags/*'

Veuillez noter que la documentation antérieure à 1.8.0.3 était ambiguë sur cet aspect du fetch --tagscomportement " ".
Valider f0cb2f1 (2012-12-14) a fetch --tagsfait correspondre la documentation à l'ancien comportement.
Ce commit modifie la documentation pour correspondre au nouveau comportement (voir Documentation/fetch-options.txt).

Demander que toutes les balises soient extraites de la télécommande en plus de tout ce qui est récupéré .


Depuis Git 2.5 (Q2 2015) git pull --tagsest plus robuste:

Voir commit 19d122b par Paul Tan ( pyokagan) , 13 mai 2015.
(Fusionné par Junio ​​C Hamano - gitster- dans commit cc77b99 , 22 mai 2015)

pull: supprimer l' --tagserreur dans aucun cas de fusion des candidats

Depuis 441ed41 (" git pull --tags": erreur avec un meilleur message., 2007-12-28, Git 1.5.4+), afficherait git pull --tagsun message d'erreur différent s'il git-fetchne renvoyait aucun candidat à la fusion:

It doesn't make sense to pull all tags; you probably meant:
       git fetch --tags

C'est parce qu'à ce moment-là, git-fetch --tags il remplacerait toutes les refspecs configurées et il n'y aurait donc pas de candidats à la fusion. Le message d'erreur a donc été introduit pour éviter toute confusion.

Cependant, depuis c5a84e9 ( fetch --tags: récupérer les balises en plus d' autres éléments, 2013-10-30, Git 1.9.0+), git fetch --tagsrécupérerait les balises en plus de toute refspec configurée.
Par conséquent, si aucune situation de fusion des candidats ne se produit, ce n'est pas parce que--tags été définie. En tant que tel, ce message d'erreur spécial n'est plus pertinent.

Pour éviter toute confusion, supprimez ce message d'erreur.


Avec Git 2.11+ (Q4 2016) git fetch c'est plus rapide.

Voir commit 5827a03 (13 octobre 2016) de Jeff King ( peff) .
(Fusionné par Junio ​​C Hamano - gitster- dans commit 9fcd144 , 26 oct.2016 )

fetch: utilisez "rapide" has_sha1_file pour le tag suivant

Lors de la récupération à partir d'une télécommande contenant de nombreuses balises non pertinentes pour les branches que nous suivons, nous gaspillions beaucoup trop de cycles lorsque nous vérifions si l'objet pointé par une balise (que nous n'allons pas chercher!) Existe dans notre référentiel trop soigneusement.

Ce correctif apprend à utiliser HAS_SHA1_QUICK pour sacrifier la précision à la vitesse, dans les cas où nous pourrions être courageux avec un reconditionnement simultané.

Voici les résultats du script perf inclus, qui configure une situation similaire à celle décrite ci-dessus:

Test            HEAD^               HEAD
----------------------------------------------------------
5550.4: fetch   11.21(10.42+0.78)   0.08(0.04+0.02) -99.3%

Cela ne s'applique que dans une situation où:

  1. Vous avez beaucoup de packs côté client à rendre reprepare_packed_git()coûteux (la partie la plus chère est de trouver des doublons dans une liste non triée, qui est actuellement quadratique).
  2. Vous avez besoin d'un grand nombre de références de balises côté serveur qui sont des candidats pour le suivi automatique (c'est-à-dire que le client n'a pas). Chacun déclenche une relecture du répertoire du pack.
  3. Dans des circonstances normales, le client suivrait automatiquement ces balises et après une extraction importante, (2) ne serait plus vrai.
    Mais si ces balises pointent vers un historique déconnecté de ce que le client récupère, il ne suivra jamais automatiquement et ces candidats auront un impact sur chaque extraction.

Git 2.21 (février 2019) semble avoir introduit une régression lorsque la configuration remote.origin.fetchn'est pas celle par défaut ( '+refs/heads/*:refs/remotes/origin/*')

fatal: multiple updates for ref 'refs/tags/v1.0.0' not allowed

Git 2.24 (Q4 2019) ajoute une autre optimisation.

Voir commit b7e2d8b (15 sept. 2019) par Masaya Suzuki ( draftcode) .
(Fusionné par Junio ​​C Hamano - gitster- en commit 1d8b0df , 07 oct.2019 )

fetch: utiliser oidsetpour conserver les OID souhaités pour une recherche plus rapide

Pendant git fetch, le client vérifie si les OID des balises publiées sont déjà dans l'OID voulu de la demande de récupération.
Cette vérification est effectuée dans un balayage linéaire.
Pour un référentiel qui a beaucoup de références, la répétition de cette analyse prend plus de 15 minutes.

Afin d'accélérer cela, créez un oid_set pour les OID des autres arbitres.

VonC
la source
Ce fil dans git-list discute de la possibilité de modifier le comportement des git fetch <remote> <branch>balises de suivi automatique (car il met déjà à jour les suivis à distance CONTRE les intentions originales): public-inbox.org/git/…
ankostis
@ankostis Intéressant: comme Junio ​​le mentionne dans public-inbox.org/git/… , "revenir à l'ancien comportement peut être une option pour résoudre le problème discuté dans ce fil." (mais ils ne le feront pas: public-inbox.org/git/… )
VonC
Aurait-il été possible pour Git d'exposer plus de complexité inutile à l'utilisateur final, nécessitant des commandes syntaxiques au point de ressembler à des hacks pour effectuer des opérations courantes? Je ne pense pas que suffisamment de connaissances internes soient encore nécessaires.
John Fantastico
1
@JohnFantastico Je peux comprendre ce point de vue. J'ai déjà vu cela: news.ycombinator.com/item?id=16587496 . Ou hackernoon.com/… ("Les commandes Git ne sont qu'une abstraction qui fuit sur le stockage de données.")
VonC
1
@Vadorequest Merci. J'ai mis à jour la réponse et je garderai un œil sur la liste de diffusion: public-inbox.org/git/?q=fetch
VonC
131

Remarque: cette réponse n'est valable que pour git v1.8 et versions antérieures.

La plupart de cela a été dit dans les autres réponses et commentaires, mais voici une explication concise:

  • git fetchrécupère toutes les têtes de branche (ou toutes spécifiées par l'option de configuration remote.fetch), toutes les validations nécessaires pour elles et toutes les balises accessibles depuis ces branches. Dans la plupart des cas, toutes les balises sont accessibles de cette manière.
  • git fetch --tagsrécupère toutes les balises, toutes les validations nécessaires. Il ne mettra pas à jour les têtes de branche, même si elles sont accessibles à partir des balises récupérées.

Résumé: Si vous voulez vraiment être totalement à jour, en utilisant uniquement la récupération, vous devez faire les deux.

Ce n'est pas non plus "deux fois plus lent" sauf si vous voulez dire en termes de saisie sur la ligne de commande, auquel cas les alias résolvent votre problème. Il n'y a essentiellement pas de frais généraux pour faire les deux demandes, car ils demandent des informations différentes.

Cascabel
la source
2
Merci pour votre commentaire. J'exécute git dans Cygwin sur un réseau à latence élevée - c'est deux fois plus lent quand il n'y a rien à chercher non plus (environ 5 secondes).
davA
Oh wow. Git-remote fonctionne-t-il mieux? En regardant brièvement la source, je pense qu'elle ne peut faire qu'un seul appel - mais je ne suis pas totalement sûr si elle va saisir les balises non sur la branche. Honnêtement, je ne sais pas si j'ai déjà vu des étiquettes qui ne se trouvent pas sur une branche. Avec les choses dont je tire, la seule façon qui arriverait si j'attendais si longtemps que j'ai raté une version de maintenance, une version de fonctionnalité et l'arrêt de la maintenance de l'ancienne version.
Cascabel
Je pense que le problème est que 'git fetch' ne récupère que les tags sur les branches suivies . Nous avons un script qui permet aux utilisateurs de sélectionner une branche de travail, donc par défaut, il existe de nombreuses branches qui ne sont pas actuellement suivies par un individu.
davidA
Je n'ai pas encore essayé git-remote, mais c'est sur ma liste de
tâches en
7
Notez que ce git remote updaten'est pas réellement un substitut pour git fetchet git fetch --tags. git remote updatene mettra pas à jour les balises existantes qui ont changé, bien qu'il en introduise de nouvelles. Seul git fetch --tagsmettra à jour les balises déjà existantes.
larsks
48

Je vais y répondre moi-même.

J'ai déterminé qu'il y a une différence. "git fetch --tags" peut apporter toutes les balises, mais il n'apporte pas de nouveaux commits!

Il s'avère que cela doit être fait pour être totalement "à jour", c'est-à-dire répliqué un "git pull" sans la fusion:

$ git fetch --tags
$ git fetch

C'est dommage, car c'est deux fois plus lent. Si seulement "git fetch" avait une option pour faire ce qu'il fait normalement et apporter toutes les balises.

davidA
la source
Intéressant, je ne l'ai pas vécu (probablement parce que mon repo était à jour au moment de mon test.) +1
VonC
1
Que diriez-vous d'un ' git remote update myRemoteRepo': cela récupérerait-il le contenu et les balises distants ?
VonC
1
Je le fais git fetchtout le temps et cela réduit systématiquement tous les nouveaux commits et tous les nouveaux tags. Quelle version de Git utilisez-vous?
Tim Visher
4
FTR, 'git remote update myRemoteRepo' ne fonctionne pas bien - ne semble pas faire ce que fait 'git fetch && git fetch --tags', d'autant plus qu'une fusion ultérieure n'a aucun effet.
davidA
1
@TimVisher git fetchne récupérera pas les balises qui ne figurent pas dans le journal de validation d'une branche. jQuery UI le fait par exemple sur une balise de version. Nous faisons un git checkout -b temp-branch, faisons notre version, ajoutons les fichiers nécessaires pour la version, la version de mise à jour, etc., git commit -m "1.10.x" ; git tag 1.10.x; git push --tagspuis nous supprimons notre branche temporaire locale. Aucune branche distante n'atteint cette balise et git fetchne la téléchargera jamais.
gnarf
31

Le problème général ici est qu'il git fetchva chercher +refs/heads/*:refs/remotes/$remote/*. Si l'un de ces validations a des balises, ces balises seront également récupérées. Cependant, s'il existe des balises inaccessibles par aucune branche de la télécommande, elles ne seront pas récupérées.

L' --tagsoption bascule la refspec sur +refs/tags/*:refs/tags/*. Vous pourriez demander git fetchde saisir les deux. Je suis à peu près sûr de faire un que git fetch && git fetch -tvous utiliseriez la commande suivante:

git fetch origin "+refs/heads/*:refs/remotes/origin/*" "+refs/tags/*:refs/tags/*"

Et si vous vouliez en faire la valeur par défaut pour ce dépôt, vous pouvez ajouter une seconde refspec à la récupération par défaut:

git config --local --add remote.origin.fetch "+refs/tags/*:refs/tags/*"

Cela ajoutera une deuxième fetch =ligne dans le .git/configpour cette télécommande.


J'ai passé un certain temps à chercher le moyen de gérer cela pour un projet. C'est ce que j'ai trouvé.

git fetch -fup origin "+refs/*:refs/*"

Dans mon cas, je voulais ces fonctionnalités

  • Prenez toutes les têtes et les balises de la télécommande, utilisez donc refspec refs/*:refs/*
  • Écraser les branches et les balises locales avec une avance non rapide + avant la refspec
  • Remplacer la branche actuellement extraite si nécessaire -u
  • Supprimer les branches et les balises non présentes dans la télécommande -p
  • Et force à être sûr -f
gnarf
la source
Ce devrait être la réponse.
renouvelé le
+1 pour "L' --tagsoption bascule la refspec sur +refs/tags/*:refs/tags/*". Bien man git-fetchque,, semble spécifier que refspec sans le leader +( refs/tags/*:refs/tags/*).
Dmitry Minkovsky
remote.origin.fetchpar défaut +refs/heads/*:refs/remotes/origin/*, c'est- à -dire la +version, n'est-ce pas? (Cela signifie que l'origine / la branche sera remplacée, peu importe où l'origine / la branche se trouve actuellement localement.)
Robert Siemer
... et au moment de la rédaction, récent git --tags récupéraient déjà des balises en plus de tout le reste. Voir la réponse de @VonC.
Robert Siemer
10

Dans la plupart des situations, git fetchvous devez faire ce que vous voulez, c'est-à-dire «obtenir quelque chose de nouveau à partir du référentiel distant et le mettre dans votre copie locale sans fusionner avec vos succursales locales». git fetch --tagsfait exactement cela, sauf qu'il n'obtient rien sauf de nouvelles balises.

En ce sens, git fetch --tagsn’est en aucun cas un surensemble degit fetch . C'est en fait exactement le contraire.

git pull, bien sûr, n'est rien d'autre qu'un emballage pour un git fetch <thisrefspec>; git merge. Il est recommandé que vous vous habituez à faire manuel git fetchING et git mergeing avant de faire le saut git pullsimplement parce qu'il vous aide à comprendre ce qui git pullest fait en premier lieu.

Cela étant dit, la relation est exactement la même qu'avec git fetch. git pullest le surensemble de git pull --tags.

Tim Visher
la source
1
"git pull est le surensemble de git pull --tags" - mais ... 'git fetch' n'est pas le surensemble de 'git fetch --tags' donc la relation n'est pas exactement la même ...?
davA
9
Je viens de trouver cette question ... eh bien, il me semble que git pullne pas obtenir toutes les étiquettes , mais seulement ceux accessibles depuis les têtes de branche en cours. Cependant, git pull --tagsrécupère toutes les balises et est apparemment équivalent à git fetch --tags.
Archimedix
2
git fetch upstream --tags

fonctionne très bien, il n'obtiendra que de nouvelles balises et n'obtiendra aucune autre base de code.

PAnand
la source
1
upstreamest normalement appelé origin. Je pense que upstreamc'est un nom utilisé par GitHub. Dans tous les cas, le nom à utiliser est celui indiqué par git remote.
Fabio dit Réintégrer Monica le