¿Cómo tirar en múltiples ramas a la vez con git?

13

En un repositorio tengo varias ramas, entre ellas "maestro" y "desarrollo", que se configuran para rastrear ramas remotas "origen / maestro" y "origen / desarrollo".

¿Es posible especificar que quiero que tanto master como desarrollo se fusionen (avance rápido) a la vez?

Cuando lo hago git pullahora me sale algo como esto:

remote: Counting objects: 92, done.
remote: Compressing objects: 100% (56/56), done.
remote: Total 70 (delta 29), reused 28 (delta 8)
Unpacking objects: 100% (70/70), done.
From scm.my-site.com:my-repo
   5386563..902fb45  develop    -> origin/develop
   d637d67..ba81fb2  master     -> origin/master
Updating 5386563..902fb45
Fast-forward

se obtienen todas las ramas remotas, pero solo la rama en la que estoy actualmente se fusiona con su rama remota correspondiente.

Entonces tengo que hacer git checkout master...

Switched to branch 'master'
Your branch is behind 'origin/master' by 106 commits, and can be fast-forwarded.

... y luego git pullotra vez, y luego volver a desarrollar, para obtener el resultado deseado.

Sé que puedo hacer alias / scripts que sigan estos pasos. Pero quiero evitar eso si es posible, ya que es propenso a errores y no es muy eficiente .
Editar: ok déjame reformular eso. Mi objetivo no era desalentar o desaprobar la personalización de scripts / alias de git. Preferiría una solución integrada si existe :)

Superole
fuente
Lo intenté, git pull origin refs/heads/develop:refs/remotes/origin/develop refs/heads/master:refs/remotes/origin/masterpero eso provocó que el maestro remoto se fusionara con el desarrollo ..
Superole
1
¿Por qué sería propenso a errores o ineficiente? Git está destinado a ser personalizado de esta manera. Por cierto, para evitar tener que revisar cada rama, es posible que desee dividir su pullen un fetchseguido por un mergeen cada rama.
jjlin
@jjlin bien si puedo hacerlo sin revisar cada rama que pueda ayudar en la eficiencia. Es propenso a errores porque la matriz de cosas que pueden salir mal y los efectos que puede tener en el resto del script son algo complejos. No digo que no sea factible hacerlo seguro, pero sería una compensación. Así que preferiría una solución integrada si existe :)
Superole

Respuestas:

11

Puede configurar un alias que utilice git fetchcon refspecs para fusionar rápidamente sus ramas con un solo comando. Configure esto como un alias en su .gitconfigarchivo de usuario :

[alias]
    sync = "!sh -c 'git checkout --quiet --detach HEAD && \
                    git fetch origin master:master develop:develop ; \
                    git checkout --quiet -'"

Uso: git sync.

Aquí es por qué funciona:

  1. git checkout --quiet HEADcomprueba directamente tu confirmación actual, poniéndote en estado de cabeza separada De esta manera, si está activado mastero developsepara su copia de trabajo de esos punteros de rama, permitiendo que se muevan (Git no le permitirá mover las referencias de rama mientras su copia de trabajo las haya retirado).

  2. git fetch origin master:master develop:developusa refspecs con fetchpara avanzar rápidamente las ramas mastery developen su repositorio local. La sintaxis básicamente le dice a Git "aquí hay una especificación de referencia de la forma <source>:<destination>, tómala <destination>y avanza rápidamente al mismo punto que <source>". Por lo tanto, las fuentes en el alias son las ramas de origin, mientras que los destinos son las versiones locales de repositorio de esas ramas.

  3. Finalmente, git checkout --quiet -verifica la rama en la que estuvo por última vez, independientemente de si hubo o no una falla en los comandos anteriores. Entonces, si estaba encendido mastercuando corrió git sync, y todo tiene éxito, dejará el estado de la cabeza desconectada y revisará el recién actualizado master.

Vea también mi respuesta a git: ¿actualizar una sucursal local sin verificarla? .

40XUserNotFound
fuente
No entiendo bien la magia separada aquí, ¿por qué no se puede mover el puntero al maestro cuando se desprotege el desarrollo? ... de todos modos probé esto, y parece funcionar, excepto que ahora obtengo "Su rama está por delante de 'origen / desarrollo' en 1 commit".
Superole
... que se resuelve la próxima vez que tire
Superole
@Superole, ¿ qué rama está por delante origin/developcuando usa el alias? No tendría sentido si fuera su developsucursal local . Además, el puntero para master se puede mover si es developque está desprotegido, el punto es que si masterestá desprotegido, entonces no puede avanzar rápidamente masterporque eso afectaría su copia de trabajo, así que es por eso que separa la copia de trabajo de ella primero usando git checkout head. Vi otra respuesta que lo describió como "parado en una roca", tienes que bajarte de la roca antes de poder moverla.
40XUserNotFound
de hecho fue mi desarrollo local. Y la razón debe ser que esta búsqueda no actualiza las ramas de seguimiento. Según lo entiendo; un tirón irá a origen / desarrollo, y luego lo fusionará en desarrollo.
Superole
Es muy importante que esta respuesta cause fatal: bad config line xx in file xxx. que es causado por el punto y coma. tienes que ajustar todo el comando entre comillas dobles para evitar este problema.
William Leung
1

Instalar git-up . Le da el comando git-upque extraerá todas las ramas locales en su repositorio.

BillyTom
fuente
¡dulce! Lo comprobaré con seguridad.
Superole
2
je: P Las declaraciones de soporte de Windows son previsiblemente ausentes. y aún no se ha formulado una prueba rigurosa de que definitivamente no alterará su configuración de git, eliminará datos o publicará tonterías en Hacker News en su nombre. , combinado con la necesidad de Ruby, me alejó. Aunque me gusta el concepto.
Superole
Me alegra que haya un método en absoluto ... un poco desagradable, aunque cada método requiere alguna herramienta de terceros. Como este y los que tienen alguna "receta" de comandos de shell o un alias que hace uso de un shell particular (específico de la plataforma).
0xC0000022L
0

Parece que no hay una opción integrada para que git se arrastre en varias ramas. Al menos no en la versión 1.8.0. aunque la respuesta de @ Cupcake está cerca.

Sin embargo, el comentario de @ jjlin me hizo darme cuenta de que al menos no necesito tirar dos veces.

Entonces, una secuencia un poco más eficiente sería:

git pull
git checkout master
git merge origin/master
git checkout -

Inevitablemente terminé creando un alias, pero decidí dejar el tirón, y me concentré en avanzar rápidamente una rama diferente.

[alias]
ffwd = "!_() { git checkout $1 && git merge --ff-only origin/$1 && git checkout -; }; _"

Por supuesto, sin pruebas, este alias supone que proporciono un nombre válido de una rama ff'able como primer argumento, y de lo contrario tiene un comportamiento indefinido. Tampoco es óptimo para casos de uso con más de dos ramas, pero me dará lo que necesito por ahora.

git pull
git ffwd master
Superole
fuente