Que signifie FETCH_HEAD dans Git?

221

git pull --help dit:

Dans son mode par défaut, git pullest un raccourci pour git fetchsuivi de git merge FETCH_HEAD.

Qu'est-ce FETCH_HEADque c'est et qu'est-ce qui est réellement fusionné pendant git pull?

Misha Moroshko
la source
3
Remarque: depuis git 1.8.4 (août 2013), git fetch origin mastersera mis à jour origin/master, pas seulement FETCH_HEAD. Voir stackoverflow.com/a/20967347/6309
VonC
Pour plus d'informations git merge FETCH_HEAD(depuis Git 2.5, Q2 2015), voir stackoverflow.com/a/30425991/6309
VonC

Réponses:

218

FETCH_HEADest une référence éphémère, pour garder une trace de ce qui vient d'être récupéré du référentiel distant. git pullappelle d'abord git fetch, dans des cas normaux, la récupération d'une branche à distance; FETCH_HEADpointe vers la pointe de cette branche (elle stocke le SHA1 du commit, tout comme le font les branches). git pullinvoque ensuite git merge, fusionnant FETCH_HEADdans la branche actuelle.

Le résultat est exactement ce que vous attendez: la validation à la pointe de la branche distante appropriée est fusionnée dans la validation à la pointe de votre branche actuelle.

C'est un peu comme se git fetchpasser d'arguments (ou git remote update), mettre à jour toutes vos branches distantes, puis s'exécuter git merge origin/<branch>, mais utiliser en FETCH_HEADinterne à la place pour faire référence à n'importe quelle référence unique récupérée, au lieu d'avoir à nommer des choses.

Cascabel
la source
9
@Jefromi: désolé, je pense que vous avez tort: ​​pour autant que je comprends, git fetchmet à jour (fusionne) toutes les données d'objet du stockage distant, pas seulement un brunch. Donc, je ne comprends pas dans votre réponse comment git décide de la pointe de la branche à pointer FETCH_HEAD. Je ne trouve pas non plus FETCH_HEADdans la documentation git (la définition, pas les exemples). L'existence de FETCH_HEADme ressemble plus à une solution de contournement, pour faire git pullfonctionner en quelque sorte .
Alexey
14
Alexey: FETCH_HEADcorrespond à la pointe de la branche distante spécifiée par branch.<BRANCH>.mergedans la configuration du référentiel local. Ainsi, fetchbien qu'il récupère effectivement toutes les données d'objet du stockage distant, FETCH_HEADest utilisé pour indiquer où la branche distante suivie par la branche locale a avancé. Donc, si vous êtes sur la masterbranche locale et exécutez git fetch, et branch.master.mergepointe vers refs/heads/master, alors FETCH_HEADaura la même valeur origin/masterqu'immédiatement après l'opération de récupération.
larsks
4
@alexy FETCH_HEAD est décrit dans le deuxième paragraphe de la description de git fetch dans sa page de manuel. Ma réponse est correcte. Et git fetch sans arguments met à jour toutes les branches distantes pour la télécommande par défaut ... mais ce n'est certainement pas la même chose que la fusion.
Cascabel
4
Que faire FETCH_HEADsi vous récupérez toutes les branches distantes via git fetch -a?
stigi
2
@stigi La pointe de la branche de suivi à distance vers laquelle pointe votre branche actuellement extraite dans la configuration git. Veuillez voir la réponse de Larsks dans le commentaire ci-dessus.
Ankur Agarwal
19

FETCH_HEAD est une référence à la pointe de la dernière extraction, que cette extraction ait été lancée directement à l'aide de la commande fetch ou dans le cadre d'une extraction. La valeur actuelle de FETCH_HEAD est stocké dans le .gitdossier dans un fichier nommé, vous l' aurez deviné, FETCH_HEAD.

Donc, si je lance:

git fetch https://github.com/ryanmaxwell/Fragaria

FETCH_HEAD peut contenir

3cfda7cfdcf9fb78b44d991f8470df56723658d3        https://github.com/ryanmaxwell/Fragaria

Si le référentiel distant est configuré en tant que branche de suivi à distance, je peux suivre mon extraction avec une fusion de la branche de suivi. Si je ne le fais pas, je peux fusionner directement la pointe de la dernière extraction en utilisant FETCH_HEAD.

git merge FETCH_HEAD
Jonathan Mitchell
la source
1
Pour ajouter mes 5 cents. Ce qui m'a dérouté, c'est que mon FETCH_HEAD était derrière les derniers commits, même s'il faisait une nouvelle extraction qui ne renvoyait «aucun changement» (dans éclipse). Je pense que la raison en est que tous les changements depuis ma dernière extraction viennent de moi et ont été poussés vers le serveur par moi. Ainsi, une extraction ultérieure n'avait rien à voir et n'a même pas mis à jour FETCH_HEAD. Je ne sais pas si c'est une lacune de l'implémentation de GIT ou Eclipse Git.
Torge
11

Comme mentionné dans la réponse de Jonathan , FETCH_HEAD correspond au fichier .git/FETCH_HEAD. En règle générale, le fichier ressemblera à ceci:

71f026561ddb57063681109aadd0de5bac26ada9                        branch 'some-branch' of <remote URL>
669980e32769626587c5f3c45334fb81e5f44c34        not-for-merge   branch 'some-other-branch' of <remote URL>
b858c89278ab1469c71340eef8cf38cc4ef03fed        not-for-merge   branch 'yet-some-other-branch' of <remote URL>

Notez comment toutes les branches sauf une sont marquées not-for-merge. L'intrus est la branche qui a été extraite avant l'extraction. En résumé: FETCH_HEAD correspond essentiellement à la version distante de la branche actuellement extraite.

Carsten Führmann
la source
9

Je viens de découvrir et d'utiliser FETCH_HEAD. Je voulais une copie locale d'un logiciel à partir d'un serveur et je l'ai fait

git fetch gitserver release_1

gitserverest le nom de ma machine qui stocke les dépôts git. release_1est une balise pour une version du logiciel. À ma grande surprise, release_1était alors introuvable sur ma machine locale. Je devais taper

 git tag release_1 FETCH_HEAD 

pour terminer la copie de la chaîne de validations balisée (release_1) du référentiel distant vers le local. Fetch avait trouvé la balise distante, copié la validation sur ma machine locale, n'avait pas créé de balise locale, mais avait défini FETCH_HEADla valeur de la validation, afin que je puisse la trouver et l'utiliser. J'ai ensuite utilisé FETCH_HEADpour créer une balise locale qui correspondait à la balise sur la télécommande. C'est une illustration pratique de ce qui FETCH_HEADest et comment il peut être utilisé, et pourrait être utile à quelqu'un d'autre se demandant pourquoi git fetch ne fait pas ce que vous attendez naïvement.

À mon avis, il vaut mieux éviter à cette fin et une meilleure façon de réaliser ce que j'essayais de faire est

git fetch gitserver release_1:release_1

c'est-à-dire pour récupérer la version_1 et l'appeler localement_1. (C'est la source: dest, voir https://git-scm.com/book/en/v2/Git-Internals-The-Refspec ; juste au cas où vous voudriez lui donner un nom différent!)

Vous voudrez peut-être utiliser FETCH_HEADparfois: -

git fetch gitserver bugfix1234
git cherry-pick FETCH_HEAD

pourrait être un bon moyen d'utiliser le correctif de bogue numéro 1234 de votre serveur Git, et de laisser la collecte de déchets de Git pour éliminer la copie du serveur une fois que le correctif a été sélectionné dans votre branche actuelle. (Je suppose qu'il y a un bon commit tagué propre contenant l'intégralité du correctif de bogue sur le serveur!)

Ivan
la source
Commentaires intéressants. +1
VonC
Merci. J'ai édité mon message d'origine, écrit lorsque j'ai découvert FETCH_HEAD pour la première fois il y a quelques années, car il semblait encourager la copie d'une balise à l'aide de FETCH_HEAD plutôt que la syntaxe source: dest pour les refspecs. J'espère que j'ai maintenant donné un meilleur exemple de la façon dont FETCH_HEAD pourrait être utilisé.
Ivan
3

git pull est une combinaison d'une extraction suivie d'une fusion. Lorsque git fetch se produit, il note le commit de tête de ce qu'il a récupéré dans FETCH_HEAD (juste un fichier de ce nom en .git) Et ces commits sont ensuite fusionnés dans votre répertoire de travail.

manojlds
la source
3
@manjolds, qu'entendez-vous par " engagement de tête de ce qu'il a récupéré"? Git récupère tout avec fetch.
Alexey
@Alexey from git manual: git-scm.com/docs/git-fetch : Les noms des références récupérées, ainsi que les noms des objets vers lesquels ils pointent, sont écrits dans .git / FETCH_HEAD
PJ_Finnegan