¿Cómo 'git pull' en una rama que no es la actual?

126

Cuando se ejecuta git pullen la masterrama, generalmente se extrae origin/master. Estoy en una rama diferente llamada newbranch, pero necesito ejecutar un comando que hace un git pulldesde origin/masterdentro masterpero no puedo ejecutar git checkoutpara cambiar la rama seleccionada hasta después de que se complete la extracción. ¿Hay alguna forma de hacer esto?

Para dar algunos antecedentes, el repositorio almacena un sitio web. He realizado algunos cambios newbranchy los he implementado cambiando el sitio web a newbranch. Ahora que esos cambios se han fusionado aguas arriba en la mastersucursal, también estoy tratando de cambiar el sitio web a la mastersucursal. En este punto, newbranchy origin/masterson idénticos, pero se masterestá quedando atrás origin/mastery necesita ser actualizado. El problema es que si lo hago de la manera tradicional:

$ git checkout master
   # Uh oh, production website has now reverted back to old version in master
$ git pull
   # Website is now up to date again

Necesito lograr lo mismo que arriba ( git checkout master && git pull), pero sin cambiar el directorio de trabajo a una revisión anterior durante el proceso.

Malvinoso
fuente
@phi: ¡No creo que funcione, porque estoy dentro newbranchy no hay nada que esconder!
Malvinoso
Clonaría en un directorio nuevo, fusionaría newbranch en master, fusionaría master nuevamente en newbranch, y luego iría de donde estás. Master y newbranch serán lo mismo.
aet
@aet Él podría hacer eso ahora en su directorio actual haciendo git fetch; git merge origin/masterdesde dentro newbranch. No hay ningún beneficio en clonar una segunda copia completa del repositorio.
meagar
3
estrechamente relacionado: stackoverflow.com/questions/3216360/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

5

Tienes un árbol de trabajo que no quieres tocar, así que usa otro. Clone es barato, está hecho para esto.

git fetch origin master       # nice linear tree
git clone . ../wip -b master  # wip's `origin/master` is my `master`
cd ../wip                     # .
git pull origin origin/master # merge origin's origin/master
git push origin master        # job's done, turn it in.
cd ../main
rm -rf ../wip                 # wip was pushed here, wip's done

git checkout master           # payload

El problema con todas las otras respuestas aquí es que en realidad no lo hacen. Si necesita la fusión o el rebase para el que tiene configurado pull, necesita otro árbol de trabajo y el procedimiento anterior. De lo contrario solo git fetch; git checkout -B master origin/masterlo hará.

jthill
fuente
2
Cuando ejecute git checkout master, pagará la masterrama anterior porque no ha hecho una git pullen la maincarpeta para sincronizarla con origen / maestro. Esto es lo que estoy tratando de evitar.
Malvineous
El pago realizado por el clon es del antiguo maestro, pero ese pago está en un directorio que el servidor web no está mirando. La salida principal al final es del maestro totalmente fusionado que fue rechazado desde wip.
Jthill
En la línea 6 empujas la fusión (actualizada) de masternuevo origin, pero no creo que tu pago final sea de esta actualización master. No hay git pullque actualizar la masterrama en el maindirectorio, por lo tanto, a menos que me falte algo, sus comandos no son diferentes de simplemente ejecutarse git checkout masterpor sí mismos y obtener el masterárbol viejo . Si observa detenidamente, no está ejecutando ningún comando en el maindirectorio que se comunique en sentido ascendente (aparte de la línea 1, que se ejecuta antes de realizar cualquier cambio en el repositorio en sentido ascendente)
Malvineous
bueno, puedes probarlo en un repositorio de prueba o consultar los documentos push.
2013
1
@jwg en comparación con qué, por favor? Asegúrese de abordar todas las necesidades declaradas de OP.
jthill
163

Sencillo: Actualización desde una sucursal remota a una sucursal maestra actualmente no extraída :

git fetch origin master:master

donde origen es su control remoto y actualmente está desprotegido en alguna rama, por ejemplo, dev .

Si desea actualizar su rama actual además de la rama especificada de una vez:

git pull origin master:master
Martin Peter
fuente
44
Hm, parece que no siempre funciona; Acabo de recibir un mensaje para fusionarme con mi rama WIP.
underscore_d
@underscore_d igual para mí.
Greg
1
Funcionó para mí ... si se solicita la fusión, me imagino que hay cambios en su rama que está actualizando que no están comprometidos con el origen
skim
2
¿Cómo se supone que esto funcione? No funciona para mí, solo intenta fusionar origin / master en mi rama actualmente desprotegida.
mhogerheijde
3
Esto lleva al maestro a la rama actual. Esto definitivamente NO es lo que se pide. Si cambia de extracción a recuperación, esto sería exactamente lo que se solicita.
Jeff Wolski
90

Esto se responde aquí: combinar, actualizar y extraer ramas de Git sin usar las cajas

# Merge local branch foo into local branch master,
# without having to checkout master first.
# Here `.` means to use the local repository as the "remote":
git fetch . foo:master

# Merge remote branch origin/foo into local branch foo,
# without having to checkout foo first:
git fetch origin foo:foo
Thomas
fuente
2
Este es el mejor, ya que funciona con cambios locales no confirmados.
Tomasz Gandor
2
Si solo desea ponerse al día con los últimos cambios que haría git fetch origin master:master. git fetchpor sí mismo supondría que pretendía actualizar la rama actual y no alguna otra rama.
John Leidegren
2
Esta es la respuesta más simple y directa. Esta debería ser la respuesta aceptada de la OMI.
Keego
@JohnLeidegren, excepto que no siempre funciona según lo previsto. Ver comentarios a stackoverflow.com/a/42902058/274579 respuesta.
ysap
22

Como resultado, la respuesta es engañosamente simple:

$ git fetch                           # Update without changing any files
$ git branch -d master                # Remove out-of-date 'master' branch
$ git checkout --track origin/master  # Create and check out up-to-date 'master' branch

Esto le permite actualizar la masterrama sin tener que cambiar a ella hasta después de que se ha actualizado.

Malvinoso
fuente
11
Esto no hace lo que preguntaste cómo hacer.
Jthill
Como dice el comentario anterior, la pregunta que terminó haciendo no es realmente la pregunta que terminó respondiendo. Debería actualizar su pregunta de manera que se trate menos específicamente de fusionarse en una rama sin verificarla, y más acerca de pasar directamente a la versión más nueva de una rama disponible en un control remoto sin verificar primero la versión anterior.
meagar
1
Es absolutamente la respuesta que vine a buscar :)
Sophistifunk
1
No es lo que OP quería, pero me ayudó, para ser honesto.
Marcel Bro
1
@anoniim, ¿no es lo que quería el OP? ¿Te refieres al OP que acaba de responder esta pregunta?
smac89
12

Te preocupa algo que no se puede arreglar, ya que las operaciones de Git no son atómicas. Siempre tendrá un agujero donde su directorio de trabajo esté a medio camino entre las ramas, incluso si actualiza el maestro sin cambiarlo primero. Es por eso que Git no es una herramienta de implementación .

Dado que en realidad no está confirmando el código en su entorno de producción (espero), en realidad no necesita tener una sucursal verificada. Simplemente puede hacer una git fetchactualización de sus referencias remotas y luego git checkout origin/mastermover el directorio de trabajo directamente al commit al que apunta actualmenteorigin/master . Esto lo pondrá en un estado de cabeza separada, pero nuevamente, como no está cometiendo código, esto no importa.

Este es el agujero más pequeño que vas a conseguir, pero como dije, todavía existe un agujero; checkoutNo es atómico.

meagar
fuente
Entiendo las limitaciones de usar git para la implementación, el problema es que el agujero en este caso durará minutos en lugar de menos de un segundo. Sin origin/masterembargo, es una buena idea hacer el check out , eso podría ser suficiente.
Malvineous
¿Qué hace que el hoyo dure "minutos"? ¿Extrayendo datos a través de la red? Simplemente haga una git fetchantes de hacer cualquier otra cosa y elimine la transferencia real de datos.
meagar
Es minutos porque un (ahora) archivo sin seguimiento sería sobrescrito por una confirmación anterior. Así que tengo que copiar el archivo, hacer las cosas de git y luego volver a colocarlo. Los 'minutos largos' provienen de mi velocidad de escritura. (Sí, podría escribirlo, pero era solo para señalar que hacer que git haga todo por sí mismo es más rápido).
Malvineous
3

Puede usar update-ref para esto:

git fetch
git update-ref refs/heads/master origin/master
git checkout master

Tenga en cuenta que esto arrojaría cualquier confirmación local en la rama maestra. En su caso no habrá ninguno, así que está bien. Para otras personas que intentan hacer esto donde hay confirmaciones locales, no creo que sea posible, ya que la fusión solo se puede ejecutar en la rama actual.

Philip Beber
fuente
¿Sería esto equivalente a git branch --force master origin/master? Esto obliga a la cabeza local mastera señalar la cabeza de originsmaster
Keego
2

La solución de Malvineous me funciona

$ git fetch                           # Update without changing any files
$ git branch -d master                # Remove out-of-date 'master' branch
$ git checkout --track origin/master  # Create and check out up-to-date 'master' branch

Solo en dar el error


warning: not deleting branch 'master' that is not yet merged to
         'refs/remotes/origin/master', even though it is merged to HEAD.
error: The branch 'master' is not fully merged.
If you are sure you want to delete it, run 'git branch -D master'.

Entonces corro con la opción -D

Gracias

Sebastian Oscar Lopez
fuente
0

git fetch origin master:master

  • "Pulls" (en realidad busca) master.
  • Si tiene cambios en su masterque aún no se han presionado, origin/masterse fusionan en su maestro.
  • Si hay conflictos de fusión, primero deberá resolverlos.
Luziano
fuente