274 votes

Que signifie FETCH_HEAD dans Git ?

git pull --help dit :

Dans son mode par défaut, git pull est un raccourci pour git fetch suivi par git merge FETCH_HEAD .

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

3 votes

Note : depuis git 1.8.4 (août 2013), git fetch origin master va effectivement mettre à jour origin/master pas seulement FETCH_HEAD . Voir stackoverflow.com/a/20967347/6309

0 votes

Pour en savoir plus git merge FETCH_HEAD (depuis Git 2.5, Q2 2015), voir stackoverflow.com/a/30425991/6309

261voto

Jefromi Points 127932

FETCH_HEAD est un ref de courte durée, pour garder la trace de ce qui vient d'être récupéré du dépôt distant. git pull invoque d'abord git fetch dans les cas normaux, en récupérant une branche à distance ; FETCH_HEAD pointe vers l'extrémité de cette branche (il stocke le SHA1 du commit, tout comme les branches). git pull puis invoque git merge , la fusion FETCH_HEAD dans la branche actuelle.

Le résultat est exactement ce que vous attendez : le commit à l'extrémité de la branche distante appropriée est fusionné avec le commit à l'extrémité de votre branche actuelle.

C'est un peu comme faire git fetch sans arguments (ou git remote update ), en mettant à jour toutes vos branches distantes, puis en exécutant git merge origin/<branch> mais en utilisant FETCH_HEAD en interne pour faire référence à n'importe quelle référence unique recherchée, au lieu de devoir nommer les choses.

2 votes

Pull peut faire une rebase au lieu d'une fusion si vous le configurez de cette façon.

1 votes

@AdamDymitruk : Bien sûr. J'ai décrit le comportement par défaut, en me disant que si quelqu'un le modifiait, il saurait qu'il l'a modifié. (Pour être complet, le comportement est identique, en remplaçant merge FETCH_HEAD avec rebase FETCH_HEAD ).

11 votes

@Jefromi : désolé, je pense que vous avez tort : d'après ce que j'ai compris, git fetch met à jour (fusionne) toutes les données d'objet du stockage à distance, et non seulement a brunch. Donc je ne comprends pas dans votre réponse comment git décide de l'extrémité de la branche à pointer. FETCH_HEAD . Je ne trouve pas non plus FETCH_HEAD dans la documentation git (la définition, pas les exemples). L'existence de FETCH_HEAD ressemble plus à une solution de contournement, pour rendre git pull travail en quelque sorte .

28voto

Jonathan Mitchell Points 323

Le FETCH_HEAD est une référence à l'extrémité de la dernière extraction, que celle-ci 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ée dans le fichier .git dans un fichier nommé, vous l'avez deviné, FETCH_HEAD .

Donc si j'émets :

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

FETCH_HEAD peut contenir

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

Si le repo distant est configuré comme une branche de suivi à distance, je peux faire suivre mon extraction d'une fusion de la branche de suivi. Si ce n'est pas le cas, je peux fusionner l'extrémité de la dernière récupération directement en utilisant FETCH_HEAD.

git merge FETCH_HEAD

1 votes

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 si je faisais un nouveau fetch qui retournait "no changes" (dans eclipse). Je pense que la raison est que tous les changements depuis mon dernier fetch sont de moi et ont été poussés vers le serveur par moi. Ainsi, une récupération ultérieure n'avait rien à faire, et n'a même pas mis à jour le FETCH_HEAD. Je ne suis pas sûr qu'il s'agisse d'un défaut de GIT ou de l'implémentation Git d'Eclipse.

19voto

Comme mentionné dans La réponse de Jonathan , FETCH_HEAD correspond au fichier .git/FETCH_HEAD . Typiquement, 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 la récupération. En résumé : FETCH_HEAD correspond essentiellement à la version distante de la branche qui est actuellement extraite.

9voto

user3070485 Points 11

Je viens de découvrir et d'utiliser FETCH_HEAD . Je voulais une copie locale d'un logiciel depuis un serveur et j'ai fait

git fetch gitserver release_1

gitserver est le nom de ma machine qui stocke les dépôts git. release_1 est une balise pour une version du logiciel. A ma grande surprise, release_1 était alors introuvable sur ma machine locale. J'ai dû taper

 git tag release_1 FETCH_HEAD 

pour compléter la copie de la chaîne de commits étiquetés (release_1) depuis le dépôt distant vers le dépôt local. Fetch avait trouvé le tag distant, copié le commit sur ma machine locale, n'avait pas a créé une balise locale, mais a défini FETCH_HEAD à la valeur du commit, afin que je puisse le trouver et l'utiliser. J'ai ensuite utilisé FETCH_HEAD pour créer une balise locale qui corresponde à celle de la balise distante. C'est une illustration pratique de ce que FETCH_HEAD et comment il peut être utilisé, et pourrait être utile à quelqu'un d'autre qui se demande pourquoi git fetch ne fait pas ce que vous attendez naïvement.

À mon avis, il est préférable de l'éviter à cette fin et une meilleure façon d'atteindre ce que j'essayais de faire est de

git fetch gitserver release_1:release_1

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

Vous pouvez utiliser FETCH_HEAD par moments cependant:-

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 le ramasse-miettes de Git se débarrasser de la copie du serveur une fois que le correctif a été sélectionné dans votre branche actuelle. (Je suppose qu'il y a un beau commit propre et étiqueté contenant l'intégralité du correctif sur le serveur).

0 votes

Commentaires intéressants. +1

0 votes

Merci. J'ai modifié mon message original, écrit lorsque j'ai découvert FETCH_HEAD il y a quelques années, car il semblait encourager la copie d'une balise en utilisant FETCH_HEAD plutôt que la syntaxe source:dest pour les refspecs. J'espère avoir maintenant donné un meilleur exemple de l'utilisation de FETCH_HEAD.

3voto

manojlds Points 96599

Git pull est la combinaison d'un fetch suivi d'un merge. Lorsque git fetch se produit, il note le head commit de ce qu'il a récupéré dans FETCH_HEAD (juste un fichier de ce nom dans .git) et ces commits sont ensuite fusionnés dans votre répertoire de travail.

3 votes

@manjolds, que voulez-vous dire par " engagement de tête de ce qu'il a rapporté" ? Git récupère tout avec fetch.

0 votes

@Alexey du manuel git : git-scm.com/docs/git-fetch : Les noms des références qui sont récupérées, ainsi que les noms des objets vers lesquels elles pointent, sont écrits dans .git/FETCH_HEAD.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X