¿Qué significa FETCH_HEAD en Git?

221

git pull --help dice:

En su modo predeterminado, git pulles la abreviatura de git fetchseguido por git merge FETCH_HEAD.

¿Qué es esto FETCH_HEADy durante qué se fusiona realmente git pull?

Misha Moroshko
fuente
3
Nota: desde git 1.8.4 (agosto de 2013), en git fetch origin masterrealidad se actualizará origin/master, no solo FETCH_HEAD. Ver stackoverflow.com/a/20967347/6309
VonC
Para más información git merge FETCH_HEAD(desde Git 2.5, Q2 2015), consulte stackoverflow.com/a/30425991/6309
VonC

Respuestas:

218

FETCH_HEADes una referencia de corta duración, para realizar un seguimiento de lo que se acaba de obtener del repositorio remoto. git pullprimero invoca git fetch, en casos normales, obtener una rama del control remoto; FETCH_HEADapunta a la punta de esta rama (almacena el SHA1 de la confirmación, tal como lo hacen las ramas). git pullluego invoca git merge, fusionandoFETCH_HEAD en la rama actual.

El resultado es exactamente lo que esperaría: la confirmación en la punta de la rama remota apropiada se fusiona en la confirmación en la punta de su rama actual.

Esto es un poco como git fetchprescindir de argumentos (o git remote update), actualizar todas sus ramas remotas, luego ejecutar git merge origin/<branch>, pero usar FETCH_HEADinternamente en su lugar para referirse a cualquier referencia individual que se haya obtenido, en lugar de tener que nombrar cosas.

Cascabel
fuente
99
@Jefromi: lo siento, creo que estás equivocado: por lo que yo entiendo, git fetchactualiza (combina) todos los datos de objetos del almacenamiento remoto, no solo un brunch. Entonces, no entiendo por su respuesta cómo git decide la punta de qué rama señalar FETCH_HEAD. Tampoco puedo encontrar FETCH_HEADen la documentación de git (la definición, no ejemplos). La existencia de FETCH_HEADme parece más como una solución, para hacer que el git pulltrabajo de alguna manera .
Alexey
14
Alexey: FETCH_HEADcorresponde a la punta de la rama remota especificada branch.<BRANCH>.mergeen la configuración del repositorio local. Por lo tanto, fetchsi bien de hecho obtiene todos los datos del objeto del almacenamiento remoto, FETCH_HEADse usa para indicar hacia dónde ha avanzado la rama remota rastreada por la rama local. Entonces, si está en la masterrama local y ejecuta git fetch, y branch.master.mergeseñala refs/heads/master, entonces FETCH_HEADtendrá el mismo valor que origin/masterinmediatamente después de la operación de recuperación.
Larsks
44
@alexy FETCH_HEAD se describe en el segundo párrafo de la descripción de git fetch en su página de manual. Mi respuesta es correcta Y git fetch sin argumentos actualiza todas las ramas remotas para el control remoto predeterminado ... pero esto definitivamente no es lo mismo que fusionar.
Cascabel
44
¿Qué FETCH_HEADsucede si obtiene todas las ramas remotas a través de git fetch -a?
stigi
2
@stigi La punta de la rama de seguimiento remoto a la que está apuntando su rama actualmente desprotegida en la configuración de git. Consulte la respuesta de los larsks en el comentario anterior.
Ankur Agarwal
19

FETCH_HEAD es una referencia a la punta de la última búsqueda, ya sea que la búsqueda se haya iniciado directamente utilizando el comando fetch o como parte de una extracción. El valor actual de FETCH_HEAD se almacena en la .gitcarpeta en un archivo llamado, lo has adivinado,FETCH_HEAD .

Entonces, si publico:

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

FETCH_HEAD puede contener

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

Si tengo el repositorio remoto configurado como una rama de seguimiento remota, entonces puedo seguir mi búsqueda con una fusión de la rama de seguimiento. Si no lo hago, puedo fusionar la punta de la última búsqueda directamente usando FETCH_HEAD.

git merge FETCH_HEAD
Jonathan Mitchell
fuente
1
Para agregar mis 5 centavos. Lo que me confundió es que mi FETCH_HEAD estaba detrás de las últimas confirmaciones, incluso si estaba haciendo una nueva búsqueda que devolvió "sin cambios" (en eclipse). Creo que la razón es que todos los cambios desde mi última búsqueda provienen de mí y fueron empujados al servidor por mí. Por lo tanto, una búsqueda posterior no tuvo nada que hacer y ni siquiera actualizó FETCH_HEAD. Sin embargo, no estoy seguro de si esto es una deficiencia de la implementación de GIT o Eclipse Git.
Torge
11

Como se menciona en la respuesta de Jonathan , FETCH_HEAD corresponde al archivo .git/FETCH_HEAD. Por lo general, el archivo se verá así:

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>

Observe cómo se marcan todas las ramas menos una not-for-merge. La extraña es la rama que se desprotegió antes de la recuperación. En resumen: FETCH_HEAD corresponde esencialmente a la versión remota de la rama que está actualmente desprotegida.

Carsten Führmann
fuente
9

Acabo de descubrir y usar FETCH_HEAD. Quería una copia local de algún software de un servidor y lo hice

git fetch gitserver release_1

gitserveres el nombre de mi máquina que almacena repositorios git. release_1es una etiqueta para una versión del software. Para mi sorpresa, release_1no se encontraba en ninguna parte de mi máquina local. Tuve que escribir

 git tag release_1 FETCH_HEAD 

para completar la copia de la cadena de confirmaciones etiquetada (release_1) desde el repositorio remoto al local. Fetch encontró la etiqueta remota, copió el commit en mi máquina local, no creó una etiqueta local, pero configuró FETCH_HEADel valor del commit para poder encontrarla y usarla. Luego solía FETCH_HEADcrear una etiqueta local que coincidía con la etiqueta en el control remoto. Esa es una ilustración práctica de lo queFETCH_HEAD es y cómo se puede usar, y podría ser útil para que alguien se pregunte por qué git fetch no hace lo que uno esperaría ingenuamente.

En mi opinión, es mejor evitarlo para ese propósito y una mejor manera de lograr lo que estaba tratando de hacer es

git fetch gitserver release_1:release_1

es decir, obtener release_1 y llamarlo release_1 localmente. (Es la fuente: dest, consulte https://git-scm.com/book/en/v2/Git-Internals-The-Refspec ; ¡en caso de que desee darle un nombre diferente!)

Sin FETCH_HEADembargo, es posible que desee usar a veces:

git fetch gitserver bugfix1234
git cherry-pick FETCH_HEAD

podría ser una buena manera de usar el número de corrección de errores 1234 de su servidor Git, y dejar la recolección de basura de Git para deshacerse de la copia del servidor una vez que la solución se ha seleccionado en su rama actual. (¡Supongo que hay una buena confirmación etiquetada limpia que contiene toda la corrección de errores en el servidor!)

Ivan
fuente
Comentarios interesantes +1
VonC
Gracias. Edité mi publicación original, escrita cuando descubrí por primera vez FETCH_HEAD hace un par de años, ya que parecía alentar la copia de una etiqueta usando FETCH_HEAD en lugar de la sintaxis de origen: dest para especificaciones. Espero haber dado un mejor ejemplo de cómo FETCH_HEAD podría usarse.
Ivan
3

git pull es una combinación de una búsqueda seguida de una fusión. Cuando sucede git fetch, observa la confirmación de la cabeza de lo que obtuvo en FETCH_HEAD (solo un archivo con ese nombre en .git) Y estas confirmaciones se fusionan en su directorio de trabajo.

manojlds
fuente
3
@manjolds, ¿qué quieres decir con " compromiso principal de lo que trajo"? Git busca todo con fetch.
Alexey
@Alexey del manual de git: git-scm.com/docs/git-fetch : los nombres de las referencias que se obtienen, junto con los nombres de los objetos a los que apuntan, se escriben en .git / FETCH_HEAD
PJ_Finnegan el