Trabajo en un proyecto que tiene 2 ramas, A y B. Normalmente trabajo en la rama A, y fusiono cosas de la rama B. Para la fusión, normalmente haría:
git merge origin/branchB
Sin embargo, también me gustaría mantener una copia local de la rama B, ya que ocasionalmente puedo revisar la rama sin fusionarme primero con mi rama A. Para esto, haría:
git checkout branchB
git pull
git checkout branchA
¿Hay alguna manera de hacer lo anterior en un comando, y sin tener que cambiar de rama de un lado a otro? ¿Debo estar usando git update-ref
para eso? ¿Cómo?
git
git-merge
git-pull
git-checkout
Charles
fuente
fuente
--no-ff
opción, lo que hace que se grabe un compromiso de fusión de todos modos. Si está interesado en eso, mi respuesta allí muestra cómo podría hacer eso, no tan robusto como mi respuesta publicada aquí, pero las fortalezas de los dos sin duda podrían combinarse.Respuestas:
La respuesta corta
Siempre y cuando esté haciendo una fusión de avance rápido , simplemente puede usar
Ejemplos:
Si bien la respuesta de Amber también funcionará en casos de avance rápido, el uso
git fetch
de esta manera en su lugar es un poco más seguro que simplemente mover la referencia de rama a la fuerza, ya quegit fetch
evitará automáticamente el avance no acelerado accidental siempre que no lo use+
en el refspec.La larga respuesta
No puede fusionar una rama B en la rama A sin desproteger A primero si daría como resultado una fusión que no sea de avance rápido. Esto se debe a que se necesita una copia de trabajo para resolver posibles conflictos.
Sin embargo, en el caso de las fusiones de avance rápido, esto es posible porque tales fusiones nunca pueden generar conflictos, por definición. Para hacer esto sin verificar primero una rama, puede usar
git fetch
una refspec.Aquí hay un ejemplo de actualización
master
(no permitir cambios que no sean de avance rápido) si tiene otra ramafeature
desprotegida:Este caso de uso es tan común, que probablemente desee crear un alias en su archivo de configuración de git, como este:
Lo que hace este alias es lo siguiente:
git checkout HEAD
: esto pone su copia de trabajo en un estado de cabeza separada. Esto es útil si desea actualizarmaster
mientras lo tiene desprotegido. Creo que fue necesario hacerlo porque, de lo contrario, la referencia de la ramamaster
no se moverá, pero no recuerdo si eso realmente está fuera de mi alcance.git fetch upstream master:master
: esto adelanta rápidamente su localmaster
al mismo lugar queupstream/master
.git checkout -
desprotege su rama desprotegida anteriormente (eso es lo que-
hace en este caso).La sintaxis de
git fetch
fusiones de avance rápido (no)Si desea que el
fetch
comando falle si la actualización no es de avance rápido, simplemente use una especificación de referencia del formularioSi desea permitir actualizaciones que no sean de avance rápido, entonces agregue un
+
al frente de la especificación de referencia:Tenga en cuenta que puede pasar su repositorio local como el parámetro "remoto" usando
.
:La documentación
De la
git fetch
documentación que explica esta sintaxis (énfasis mío):Ver también
Git checkout y fusionar sin tocar el árbol de trabajo
Fusionar sin cambiar el directorio de trabajo
fuente
git checkout --quiet HEAD
es agit checkout --quiet --detach
partir de Git 1.7.5.git fetch . origin/foo:foo
actualizar mi foo local a mi origen / foo localgit checkout -
truco! Tan fácil comocd -
.No no hay. Es necesario realizar un pago de la rama objetivo para permitirle resolver conflictos, entre otras cosas (si Git no puede fusionarlos automáticamente).
Sin embargo, si la fusión es rápida, no necesita verificar la rama de destino, porque en realidad no necesita fusionar nada; todo lo que tiene que hacer es actualizar la rama para señalar nuevo cabezal ref. Puedes hacer esto con
git branch -f
:Se actualizará
branch-b
para apuntar a la cabeza debranch-a
.La
-f
opción significa--force
, lo que significa que debe tener cuidado al usarla.fuente
git reset
solo funciona en la rama actualmente desprotegida.git fetch upstream branch-b:branch-b
(tomado de esta respuesta ).git fetch <remote> B:A
, donde B y A son ramas completamente diferentes, pero B puede avanzar rápidamente en A. También puede pasar su repositorio local como "remoto" usando.
como alias remoto:git fetch . B:A
.branch -f
podría ser peligroso, como usted señala. ¡Así que no lo uses! Usofetch origin branchB:branchB
, que fallará de forma segura si la fusión no avanza rápidamente.Como dijo Amber, las fusiones de avance rápido son el único caso en el que posiblemente podría hacer esto. Cualquier otra combinación posiblemente deba pasar por la combinación completa de tres vías, aplicar parches, resolver conflictos y eso significa que debe haber archivos.
Resulta que tengo un script que utilizo exactamente para esto: hacer fusiones de avance rápido sin tocar el árbol de trabajo (a menos que se esté fusionando en HEAD). Es un poco largo, porque es al menos un poco robusto: verifica para asegurarse de que la fusión sea un avance rápido, luego lo realiza sin verificar la rama, pero produce los mismos resultados que si lo hubiera hecho.
diff --stat
resumen de los cambios, y la entrada en el registro de registro es exactamente como una combinación de avance rápido, en lugar del "restablecimiento" que obtienes si lo usasbranch -f
. Si lo que seagit-merge-ff
y colocar en el directorio bin, se le puede llamar como un comando git:git merge-ff
.PD: si alguien ve algún problema con ese script, ¡comente! Era un trabajo de escribir y olvidar, pero estaría feliz de mejorarlo.
fuente
# or git branch -f localbranch remote/remotebranch
me recuerda la fuente y las opciones. Dio su comentario en el otro enlace a +1."$branch@{u}"
como el compromiso de fusión para obtener la rama ascendente (desde kernel.org/pub/software/scm/git/docs/gitrevisions.html )Solo puede hacer esto si la fusión es un avance rápido. Si no es así, ¡git necesita que se revisen los archivos para que pueda fusionarlos!
Para hacerlo solo para un avance rápido :
dónde
<commit>
está el commit recuperado, al que desea avanzar rápidamente. Esto es básicamente como usargit branch -f
para mover la rama, excepto que también la registra en el registro como si realmente hubiera hecho la fusión.Por favor, por favor, no hagas esto por algo que no sea un avance rápido, o simplemente restablecerás tu rama a la otra confirmación. (Para verificar, ver si
git merge-base <branch> <commit>
da SHA1 de la sucursal).fuente
git merge-base --is-ancestor <A> <B>
. "B" es lo que necesita fusionarse en "A". El ejemplo sería A = maestro y B = desarrollar, asegurándose de que el desarrollo sea rápido reenviable en maestro. Nota: existe con 0 si no es ff-able, existe con 1 si lo es.En tu caso puedes usar
que hace lo que quiere (suponiendo que la fusión es un avance rápido). Si la rama no se puede actualizar porque requiere una fusión que no sea de avance rápido, entonces esto falla de manera segura con un mensaje.
Esta forma de búsqueda también tiene algunas opciones más útiles:
Tenga en cuenta que
<remote>
puede ser un repositorio local y<sourceBranch>
puede ser una rama de seguimiento. Por lo tanto, puede actualizar una sucursal local, incluso si no está desprotegida, sin acceder a la red .Actualmente, mi acceso al servidor ascendente es a través de una VPN lenta, por lo que me conecto periódicamente
git fetch
para actualizar todos los controles remotos y luego desconectarme. Entonces, si, por ejemplo, el maestro remoto ha cambiado, puedo hacerpara actualizar de forma segura a mi maestro local, incluso si actualmente tengo alguna otra sucursal desprotegida. No se requiere acceso a la red.
fuente
Otra forma, sin duda, bastante brutal es simplemente volver a crear la rama:
Esto desecha la rama local obsoleta y vuelve a crear una con el mismo nombre, así que úsala con cuidado ...
fuente
Puede clonar el repositorio y fusionarlo en el nuevo repositorio. En el mismo sistema de archivos, esto enlazará en lugar de copiar la mayoría de los datos. Termine colocando los resultados en el repositorio original.
fuente
Ingrese git-forward-merge :
https://github.com/schuyler1d/git-forward-merge
Solo funciona para fusiones automáticas, si hay conflictos necesita usar la fusión regular.
fuente
Para muchos casos (como la fusión), puede usar la rama remota sin tener que actualizar la rama de seguimiento local. Agregar un mensaje al reflog suena como una exageración y evitará que sea más rápido. Para facilitar la recuperación, agregue lo siguiente en su configuración de git
Luego escribe
para ver el historial reciente de tu sucursal
fuente
[core]
no[user]
? (y estáEscribí una función de shell para un caso de uso similar que encuentro a diario en proyectos. Esto es básicamente un atajo para mantener actualizadas las sucursales locales con una sucursal común como desarrollar antes de abrir un RP, etc.
glmh
("git pull and merge here") automáticamentecheckout branchB
,pull
lo último, recheckout branchA
ymerge branchB
.No aborda la necesidad de mantener una copia local de la rama A, pero podría modificarse fácilmente para hacerlo agregando un paso antes de retirar la rama B. Algo como...
Para fusiones de avance rápido simples, esto salta al mensaje de confirmación del mensaje.
Para las fusiones no avanzadas, esto coloca a su sucursal en el estado de resolución de conflictos (es probable que deba intervenir).
Para configurar, agregar
.bashrc
o.zshrc
, etc.:Uso:
fuente
Otra forma de hacer esto de manera efectiva es:
Debido a que es una minúscula
-d
, solo lo eliminará si los datos aún existen en algún lugar. Es similar a la respuesta de @kkoehne, excepto que no obliga. Por el-t
esto, configurará el control remoto nuevamente.Tenía una necesidad ligeramente diferente de OP, que era crear una nueva rama de función
develop
(omaster
), después de fusionar una solicitud de extracción. Eso se puede lograr en una sola línea sin fuerza, pero no actualiza ladevelop
rama local . Es solo una cuestión de verificar una nueva sucursal y hacer que se baseorigin/develop
:fuente
solo para extraer el maestro sin verificar el maestro que uso
git fetch origin master:master
fuente
Es absolutamente posible hacer cualquier combinación, incluso las combinaciones de avance no rápido, sin
git checkout
. Laworktree
respuesta de @grego es una buena pista. Para ampliar sobre eso:Ahora ha fusionado la rama de trabajo local a la
master
rama local sin cambiar su pago.fuente
Si desea mantener el mismo árbol que una de las ramas que desea fusionar (es decir, no una "fusión" real), puede hacerlo así.
fuente
Puede intentar
git worktree
tener dos ramas abiertas una al lado de la otra, parece que podría ser lo que desea, pero es muy diferente a algunas de las otras respuestas que he visto aquí.De esta manera, puede tener dos ramas separadas rastreando en el mismo repositorio de git, por lo que solo tiene que buscar una vez para obtener actualizaciones en ambos árboles de trabajo (en lugar de tener que clonar dos veces y tirar de cada una)
Worktree creará un nuevo directorio de trabajo para su código donde puede tener una rama diferente extraída simultáneamente en lugar de intercambiar ramas en su lugar.
Cuando desee eliminarlo, puede limpiar con
fuente