¿"Git fetch --tags" incluye "git fetch"?


270

Una pregunta agradable y simple: ¿es la función de "git fetch" un subconjunto estricto de git fetch --tags?

Es decir, si corro git fetch --tags, ¿hay alguna razón para correr git fetchinmediatamente después?

¿Qué hay de git pully git pull --tags? ¿Misma situacion?


11
Comenzando Git 1..9 / 2.0 (Q1 2014), la respuesta será . Vea mi respuesta a continuación
VonC

3
Para el editor que "corrigió mi texto" con una edición, uno no necesariamente escribe en mayúsculas después de un guión o un acrónimo, por lo que su edición fue gramaticalmente incorrecta, por lo que la rechacé.
davidA

Respuestas:


176

Nota: comenzando con git 1.9 / 2.0 (Q1 2014) , git fetch --tagsobtiene etiquetas además de las obtenidas por la misma línea de comando sin la opción.

Ver commit c5a84e9 por Michael Haggerty (mhagger) :

Anteriormente, la --tagsopción " " de búsqueda se consideraba equivalente a especificar la especificación de referencia

refs/tags/*:refs/tags/*

en la línea de comando; en particular, hizo remote.<name>.refspecque se ignorara la configuración.

Pero no es muy útil buscar etiquetas sin también buscar otras referencias, mientras que es bastante útil poder obtener etiquetas además de otras referencias.
Así que cambie la semántica de esta opción para hacer la última.

Si un usuario desea obtener solo etiquetas, aún es posible especificar una especificación de referencia explícita:

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

Tenga en cuenta que la documentación anterior a 1.8.0.3 era ambigua sobre este aspecto del " fetch --tags" comportamiento.
Commit f0cb2f1 (2012-12-14) fetch --tagshizo que la documentación coincida con el comportamiento anterior.
Esta confirmación cambia la documentación para que coincida con el nuevo comportamiento (ver Documentation/fetch-options.txt).

Solicite que todas las etiquetas se obtengan del control remoto además de cualquier otra cosa que se obtenga .


Dado que Git 2.5 (Q2 2015) git pull --tagses más robusto:

Ver commit 19d122b por Paul Tan ( pyokagan) , 13 de mayo de 2015.
(Fusión por Junio ​​C Hamano - gitster- en commit cc77b99 , 22 de mayo de 2015)

pull: eliminar --tagserror en caso de candidatos no fusionados

Dado que 441ed41 (" git pull --tags": error con un mensaje mejor., 28/12/2007, Git 1.5.4+), git pull --tagsimprimiría un mensaje de error diferente si git-fetchno devuelve ningún candidato de fusión:

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

Esto se debe a que, en ese momento, git-fetch --tagsanularía cualquier especificación de referencia configurada y, por lo tanto, no habría candidatos para la fusión. El mensaje de error se introdujo así para evitar confusiones.

Sin embargo, desde c5a84e9 ( fetch --tags: buscar etiquetas además de otras cosas, 2013-10-30, Git 1.9.0+), git fetch --tagsbuscaría etiquetas además de cualquier refspecs configurado.
Por lo tanto, si ocurre una situación de candidatos sin fusión, no es porque --tagsse estableció. Como tal, este mensaje de error especial ahora es irrelevante.

Para evitar confusiones, elimine este mensaje de error.


Con Git 2.11+ (Q4 2016) git fetches más rápido.

Ver commit 5827a03 (13 de octubre de 2016) por Jeff King ( peff) .
(Fusionada por Junio ​​C Hamano - gitster- en commit 9fcd144 , 26 oct 2016)

fetch: utilice "rápido" has_sha1_filepara seguir la etiqueta

Al buscar desde un control remoto que tiene muchas etiquetas que son irrelevantes para las ramas que estamos siguiendo, solíamos desperdiciar demasiados ciclos al verificar si el objeto señalado por una etiqueta (¡que no vamos a buscar!) Existe en nuestro repositorio con mucho cuidado

Este parche enseña a fetch a usar HAS_SHA1_QUICK para sacrificar la precisión por la velocidad, en los casos en que podríamos ser rápidos con un reempaque simultáneo.

Estos son los resultados del script de perf incluido, que establece una situación similar a la descrita anteriormente:

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

Eso solo se aplica a una situación en la que:

  1. Tiene muchos paquetes en el lado del cliente para hacer que sea reprepare_packed_git()costoso (la parte más costosa es encontrar duplicados en una lista sin clasificar, que actualmente es cuadrática).
  2. Necesita una gran cantidad de referencias de etiquetas en el lado del servidor que sean candidatos para el seguimiento automático (es decir, que el cliente no tiene). Cada uno desencadena una relectura del directorio del paquete.
  3. En circunstancias normales, el cliente seguiría automáticamente esas etiquetas y después de una búsqueda grande, (2) ya no sería cierto.
    Pero si esas etiquetas apuntan al historial que está desconectado de lo que el cliente obtiene, entonces nunca se seguirá automáticamente, y esos candidatos lo afectarán en cada búsqueda.

Git 2.21 (febrero de 2019) parece haber introducido una regresión cuando la configuración noremote.origin.fetch es la predeterminada ( '+refs/heads/*:refs/remotes/origin/*')

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

Git 2.24 (Q4 2019) agrega otra optimización.

Ver commit b7e2d8b (15 sep 2019) por Masaya Suzuki ( draftcode) .
(Fusionada por Junio ​​C Hamano - gitster- en commit 1d8b0df , 07 oct 2019)

fetch: use oidsetpara mantener los OID deseados para una búsqueda más rápida

Durante git fetch, el cliente comprueba si los OID de las etiquetas anunciadas ya están en el conjunto de OID deseado de la solicitud de búsqueda.
Esta verificación se realiza en un escaneo lineal.
Para un repositorio que tiene muchas referencias, repetir este análisis lleva más de 15 minutos.

Para acelerar esto, cree un oid_setOID para otras referencias.


Este hilo en git-list discute la posibilidad de enmendar el comportamiento de git fetch <remote> <branch>las etiquetas de seguimiento automático (ya que ya actualiza los seguimientos remotos CONTRA las intenciones originales): public-inbox.org/git/…
ankostis

@ankostis Interesante: como menciona Junio ​​en public-inbox.org/git/… , "volver al comportamiento anterior puede ser una opción para abordar el problema que se discute en este hilo". (pero no lo harán: public-inbox.org/git/… )
VonC

¿Habría sido posible que Git exponga más complejidad innecesaria al usuario final, requiriendo comandos pesados ​​de sintaxis hasta el punto de parecerse a los hacks para realizar operaciones comunes? No creo que suficiente de lo interno sea un conocimiento requerido todavía.
John Fantastico

1
@JohnFantastico Puedo entender ese punto de vista. Lo he visto antes: news.ycombinator.com/item?id=16587496 . O hackernoon.com/… ("Los comandos de Git son solo una abstracción permeable sobre el almacenamiento de datos")
VonC

1
@Vadorequest Gracias. He actualizado la respuesta y estaré atento
VonC

131

Nota: esta respuesta solo es válida para git v1.8 y anteriores.

La mayor parte de esto se ha dicho en las otras respuestas y comentarios, pero aquí hay una explicación concisa:

  • git fetchrecupera todos los encabezados de rama (o todos los especificados por la opción de configuración remote.fetch), todas las confirmaciones necesarias para ellos y todas las etiquetas a las que se puede acceder desde estas ramas. En la mayoría de los casos, todas las etiquetas son accesibles de esta manera.
  • git fetch --tagsrecupera todas las etiquetas, todas las confirmaciones necesarias para ellas. Será no actualizar directores de las sucursales, incluso si son accesibles desde las etiquetas que eran descabellada.

Resumen: si realmente desea estar totalmente actualizado, utilizando solo fetch, debe hacer ambas cosas.

Tampoco es "el doble de lento" a menos que se refiera a escribir en la línea de comandos, en cuyo caso los alias resuelven su problema. Esencialmente no hay gastos generales al hacer las dos solicitudes, ya que están solicitando información diferente.


2
Gracias por tu comentario. Estoy ejecutando git en Cygwin a través de una red de alta latencia: es el doble de lento cuando no hay nada que buscar (unos 5 segundos).
davidA

Oh wow. ¿Git-remote funciona mejor? Mirando brevemente la fuente, creo que puede hacer una sola llamada, pero no estoy totalmente seguro de si tomará las etiquetas que no están en la rama. Honestamente, no sé si alguna vez he visto alguna etiqueta que no esté en una rama. Con las cosas que saco, la única forma en que sucedería si esperaba tanto tiempo que me perdí una versión de mantenimiento, una versión de características y la interrupción del mantenimiento de la versión anterior.
Cascabel

Creo que el problema es que 'git fetch' solo busca etiquetas en las ramas rastreadas . Tenemos una secuencia de comandos que permite a los usuarios seleccionar una rama de trabajo, por lo que, de forma predeterminada, hay muchas ramas que actualmente no son rastreadas por un individuo.
davidA

No he probado git-remote todavía, pero está en mi lista de cosas por hacer cada vez más :)
davidA

77
Tenga en cuenta que en git remote updaterealidad no es un sustituto de git fetchy git fetch --tags. git remote updateno actualizará las etiquetas existentes que han cambiado, aunque traerá nuevas etiquetas. Solo git fetch --tagsactualizará las etiquetas ya existentes.
larsks

48

Voy a responder esto yo mismo.

He determinado que hay una diferencia. "git fetch --tags" puede traer todas las etiquetas, ¡pero no trae nuevos commits!

Resulta que uno tiene que hacer esto para estar totalmente "actualizado", es decir, replicar un "git pull" sin la fusión:

$ git fetch --tags
$ git fetch

Es una pena, porque es el doble de lento. Si solo "git fetch" tuviera la opción de hacer lo que normalmente hace y traer todas las etiquetas.


Interesante, no experimenté eso (probablemente porque mi repositorio estaba actualizado en el momento de mi prueba). +1
VonC

1
¿Qué tal un ' git remote update myRemoteRepo': eso buscaría contenido remoto y etiquetas?
VonC

1
Lo hago git fetchtodo el tiempo y constantemente elimina cualquier nueva confirmación y cualquier nueva etiqueta. ¿Qué versión de Git estás ejecutando?
Tim Visher

44
FTR, 'git remote update myRemoteRepo' no funciona bien, no parece hacer lo que hace 'git fetch && git fetch --tags', especialmente porque una fusión posterior no tiene ningún efecto.
davidA

1
@TimVisher git fetchno tomará etiquetas que no estén en el registro de confirmación de una rama. jQuery UI hace esto, por ejemplo, en una etiqueta de lanzamiento. Hacemos un git checkout -b temp-branch, hacemos nuestro lanzamiento, agregamos los archivos necesarios para el lanzamiento, actualizamos la versión, etc., git commit -m "1.10.x" ; git tag 1.10.x; git push --tagsluego eliminamos nuestra rama temporal local. No hay una rama remota que llegue a esa etiqueta y git fetchnunca la descargará.
Gnarf

31

El problema general aquí es que git fetchbuscará +refs/heads/*:refs/remotes/$remote/*. Si alguno de estos commits tiene etiquetas, esas etiquetas también se recuperarán. Sin embargo, si hay ramas a las que ninguna rama en el control remoto pueda acceder, no se recuperarán.

La --tagsopción cambia la especificación de referencia a +refs/tags/*:refs/tags/*. Usted podría pedir git fetcha agarrar ambos. Estoy bastante seguro de que solo haría un git fetch && git fetch -tusaría el siguiente comando:

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

Y si desea hacer que esto sea el predeterminado para este repositorio, puede agregar una segunda especificación de referencia a la búsqueda predeterminada:

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

Esto agregará una segunda fetch =línea .git/configpara este control remoto.


Pasé un tiempo buscando la manera de manejar esto para un proyecto. Esto es lo que se me ocurrió.

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

En mi caso quería estas características

  • Tome todas las cabezas y etiquetas del control remoto, así que use refspec refs/*:refs/*
  • Sobrescribir ramas y etiquetas locales con avance no rápido +antes de la especificación de referencia
  • Sobrescribir la rama actualmente desprotegida si es necesario -u
  • Eliminar ramas y etiquetas no presentes en el control remoto -p
  • Y obligar a estar seguro -f

Esta debería ser la respuesta.
olor a

+1 para "La --tagsopción cambia la especificación de referencia a +refs/tags/*:refs/tags/*". Aunque, man git-fetchparece especificar que refspec sin el líder +( refs/tags/*:refs/tags/*).
Dmitry Minkovsky

remote.origin.fetchpor defecto +refs/heads/*:refs/remotes/origin/*, es decir, la +versión, ¿no? (Eso significa que el origen / sucursal se sobrescribirá, sin importar dónde esté el origen / sucursal en este momento localmente)
Robert Siemer

... y en el momento de la escritura, recientes ya git --tagsestaban buscando etiquetas además de todo lo demás. Ver la respuesta de @VonC.
Robert Siemer

10

En la mayoría de las situaciones, git fetchdebe hacer lo que quiera, que es 'obtener algo nuevo del repositorio remoto y ponerlo en su copia local sin fusionarse con sus sucursales locales'. git fetch --tagshace exactamente eso, excepto que no obtiene nada excepto nuevas etiquetas.

En ese sentido, git fetch --tagsde ninguna manera es un superconjunto de git fetch. De hecho, es exactamente lo contrario.

git pull, por supuesto, no es más que una envoltura para a git fetch <thisrefspec>; git merge. Se recomienda que uno se acostumbra a hacer manual de git fetchING y git mergeing antes de hacer el salto a git pullsimplemente porque ayuda a entender lo que git pullestá haciendo en primer lugar.

Dicho esto, la relación es exactamente la misma que con git fetch. git pulles el superconjunto de git pull --tags.


1
"git pull es el superconjunto de git pull --tags" - pero ... 'git fetch' no es el superconjunto de 'git fetch --tags', ¿entonces la relación no es exactamente la misma ...?
davidA

9
Acabo de encontrar esta pregunta ... bueno, me parece que git pullno no conseguir todas las etiquetas, pero sólo aquellos accesible desde los directores de las sucursales actuales. Sin embargo, git pull --tagsobtiene todas las etiquetas y aparentemente es equivalente a git fetch --tags.
Archimedix

2
git fetch upstream --tags

funciona bien, solo obtendrá nuevas etiquetas y no obtendrá ninguna otra base de código.


1
upstreamse llama normalmente origin. Creo que upstreames un nombre usado por GitHub. En cualquier caso, el nombre a usar es el que se muestra con git remote.
Fabio dice reinstalar a Mónica el
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.