tag remota rama crear cambiar git git-merge git-pull git-checkout

remota - git push



Combine, actualice y extraiga sucursales de Git sin usar cajas. (10)

La respuesta corta

Mientras esté haciendo una combinación de avance rápido , simplemente puede usar

git fetch <remote> <sourceBranch>:<destinationBranch>

Ejemplos:

# 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

Si bien la respuesta de Amber también funcionará en casos de avance rápido, usar git fetch de esta manera es un poco más seguro que solo mover la fuerza de la referencia, ya que git fetch evitará automáticamente el avance no rápido hacia adelante siempre que no lo hagas. t usar + en la refspec.

La respuesta larga

No puede fusionar una rama B en la rama A sin desproteger A primero si esto resultaría en una combinación sin avance rápido. Esto se debe a que se necesita una copia de trabajo para resolver cualquier conflicto potencial.

Sin embargo, en el caso de fusiones rápidas, esto es posible , porque tales fusiones nunca pueden dar lugar a conflictos, por definición. Para hacer esto sin verificar primero una rama, puede usar git fetch con un refspec.

Este es un ejemplo de la actualización del master (que no permite cambios que no se adelantan) si tiene otra feature bifurcación activada:

git fetch upstream master:master

Este caso de uso es tan común, que probablemente querrá hacer un alias para él en su archivo de configuración de git, como este:

[alias] sync = !sh -c ''git checkout --quiet HEAD; git fetch upstream master:master; git checkout --quiet -''

Lo que hace este alias es lo siguiente:

  1. git checkout HEAD : esto pone su copia de trabajo en un estado de cabeza separada. Esto es útil si desea actualizar el master mientras que lo tiene desprotegido. Creo que era necesario hacerlo porque, de lo contrario, la referencia de bifurcación para el master no se moverá, pero no recuerdo si eso es realmente correcto.

  2. git fetch upstream master:master : envía rápidamente tu master local al mismo lugar que upstream/master .

  3. git checkout - revisa su sucursal previamente retirada (eso es lo que hace en este caso).

La sintaxis de git fetch para fusiones (no) de avance rápido

Si desea que el comando fetch falle si la actualización no avanza rápidamente, simplemente use una refspec del formulario

git fetch <remote> <remoteBranch>:<localBranch>

Si desea permitir actualizaciones que no sean de avance rápido, entonces agregue un + al frente de la refspec:

git fetch <remote> +<remoteBranch>:<localBranch>

Tenga en cuenta que puede pasar su repositorio local como parámetro "remoto" usando . :

git fetch . <sourceBranch>:<destinationBranch>

La documentación

De la documentación de git fetch que explica esta sintaxis (el énfasis es mío):

<refspec>

El formato de un parámetro <refspec> es un signo más + opcional, seguido de la referencia de origen <src> , seguido de dos puntos : seguido de la referencia de destino <dst> .

La referencia remota que coincide con <src> se recupera, y si <dst> no es una cadena vacía, la referencia local que coincide con ella se adelanta rápidamente utilizando <src> . Si se utiliza el plus + opcional, la referencia local se actualiza incluso si no resulta en una actualización de avance rápido.

Ver también

  1. Git checkout y fusionar sin tocar el árbol de trabajo

  2. Fusionar sin cambiar el directorio de trabajo.

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 conservar una copia local de la sucursal B, ya que ocasionalmente puedo revisar la sucursal sin fusionarme primero con mi sucursal A. Para esto, haría:

git checkout branchB git pull git checkout branchA

¿Hay una manera de hacer lo anterior en un comando, y sin tener que cambiar de bifurcación? ¿Debo usar git update-ref para eso? ¿Cómo?


Como dijo Amber, las combinaciones de avance rápido son el único caso en el que posiblemente podrías hacer esto. Cualquier otra combinación que se pueda imaginar debe pasar por la combinación de tres vías, aplicar parches, resolver conflictos, y eso significa que debe haber archivos.

Resulta que tengo una secuencia de comandos que utilizo exactamente para esto: hacer combinaciones de avance rápido sin tocar el árbol de trabajo (a menos que se esté fusionando con HEAD). Es un poco largo, porque es al menos un poco robusto; verifica que la fusión sea un avance rápido, luego lo realiza sin verificar la rama, pero produce los mismos resultados que si tuviera, ve el diff --stat resumen de los cambios de diff --stat , y la entrada en el reflog es exactamente como una combinación de avance rápido, en lugar del "reset" que se obtiene si se usa branch -f . Si lo nombra git-merge-ff y lo coloca en su directorio bin, puede llamarlo como un comando git merge-ff : git merge-ff .

#!/bin/bash _usage() { echo "Usage: git merge-ff <branch> <committish-to-merge>" 1>&2 exit 1 } _merge_ff() { branch="$1" commit="$2" branch_orig_hash="$(git show-ref -s --verify refs/heads/$branch 2> /dev/null)" if [ $? -ne 0 ]; then echo "Error: unknown branch $branch" 1>&2 _usage fi commit_orig_hash="$(git rev-parse --verify $commit 2> /dev/null)" if [ $? -ne 0 ]; then echo "Error: unknown revision $commit" 1>&2 _usage fi if [ "$(git symbolic-ref HEAD)" = "refs/heads/$branch" ]; then git merge $quiet --ff-only "$commit" else if [ "$(git merge-base $branch_orig_hash $commit_orig_hash)" != "$branch_orig_hash" ]; then echo "Error: merging $commit into $branch would not be a fast-forward" 1>&2 exit 1 fi echo "Updating ${branch_orig_hash:0:7}..${commit_orig_hash:0:7}" if git update-ref -m "merge $commit: Fast forward" "refs/heads/$branch" "$commit_orig_hash" "$branch_orig_hash"; then if [ -z $quiet ]; then echo "Fast forward" git diff --stat "$branch@{1}" "$branch" fi else echo "Error: fast forward using update-ref failed" 1>&2 fi fi } while getopts "q" opt; do case $opt in q ) quiet="-q";; * ) ;; esac done shift $((OPTIND-1)) case $# in 2 ) _merge_ff "$1" "$2";; * ) _usage esac

PD: ¡Si alguien ve algún problema con ese script, por favor comente! Era un trabajo de escribir y olvidar, pero estaría feliz de mejorarlo.


En tu caso puedes usar

git fetch origin branchB:branchB

que hace lo que usted desea (asumiendo que la fusión es un avance rápido). Si la rama no se puede actualizar porque requiere una combinación de no avance rápido, esto falla con seguridad con un mensaje.

Esta forma de búsqueda tiene algunas opciones más útiles también:

git fetch <remote> <sourceBranch>:<destinationBranch>

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 periódicamente me conecto, git fetch para actualizar todos los controles remotos y luego me desconecto. Entonces si, digamos, el maestro remoto ha cambiado, puedo hacerlo

git fetch . remotes/origin/master:master

para actualizar de manera segura a mi maestro local, incluso si actualmente tengo alguna otra sucursal desprotegida. No se requiere acceso a la red.


Escribí una función de shell para un caso de uso similar que encuentro diariamente en proyectos. Esto es básicamente un atajo para mantener las sucursales locales al día con una sucursal común como desarrollar antes de abrir un RP, etc.

Publicar esto aunque no quiera usar el proceso de checkout , en caso de que a otros no les importe esa restricción.

glmh ("git pull and merge here") checkout branchB automáticamente la checkout branchB , checkout branchB la última, checkout branchA y merge branchB

No aborda la necesidad de mantener una copia local de la sucursal A, pero podría modificarse fácilmente para hacerlo agregando un paso antes de retirar la sucursal B. Algo como...

git branch ${branchA}-no-branchB ${branchA}

Para simples fusiones de avance rápido, esto salta al indicador de mensaje de confirmación.

Para las fusiones que no son de avance rápido, esto coloca a su sucursal en el estado de resolución de conflictos (es probable que deba intervenir).

Para la configuración, agregue a .bashrc o .zshrc , etc:

glmh() { branchB=$1 [ $# -eq 0 ] && { branchB="develop" } branchA="$(git branch | grep ''*'' | sed ''s/* //g'')" git checkout ${branchB} && git pull git checkout ${branchA} && git merge ${branchB} }

Uso:

# No argument given, will assume "develop" > glmh # Pass an argument to pull and merge a specific branch > glmh your-other-branch

Nota: Esto no es lo suficientemente robusto como para transferir args más allá del nombre de la rama a git merge


Introduzca git-forward-merge :

Sin necesidad de desproteger destino, git-forward-merge <source> <destination> combina el origen en la rama de destino.

https://github.com/schuyler1d/git-forward-merge

Solo funciona para las combinaciones automáticas, si hay conflictos, debe utilizar la combinación regular.


No no hay. Una verificación de la rama de destino es necesaria para permitirle resolver conflictos, entre otras cosas (si Git no puede fusionarlos automáticamente).

Sin embargo, si la combinación es de avance rápido, no necesita revisar la rama de destino, ya que en realidad no necesita combinar nada, todo lo que debe hacer es actualizar la rama para que apunte a la rama. nueva cabeza ref. Puedes hacer esto con git branch -f :

git branch -f branch-b branch-a

Actualizaré la branch-b para que apunte al jefe de la branch-a .

La opción -f significa --force , lo que significa que debe tener cuidado al usarla. No lo use a menos que esté seguro de que la fusión será un avance rápido.


Otra forma, sin duda bastante bruta, es simplemente volver a crear la rama:

git fetch remote git branch -f localbranch remote/remotebranch

Esto desecha la sucursal obsoleta local y recrea una con el mismo nombre, así que úsala con cuidado ...


Para muchos casos (como la fusión), puede usar la rama remota sin tener que actualizar la rama de seguimiento local. Agregar un mensaje en el 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

[core] logallrefupdates=true

Entonces escribe

git reflog show mybranch

Para ver la historia reciente de tu sucursal.


Puede clonar el repositorio y hacer la fusión en el nuevo repositorio. En el mismo sistema de archivos, esto establecerá un enlace duro en lugar de copiar la mayoría de los datos. Termina tirando de los resultados en el repositorio original.


Solo puedes hacer esto si la combinación es un avance rápido. Si no es así, entonces git necesita que se revisen los archivos para que pueda combinarlos.

Para hacerlo solo para un avance rápido :

git fetch <branch that would be pulled for branchB> git update-ref -m "merge <commit>: Fast forward" refs/heads/<branch> <commit>

donde <commit> es el compromiso recuperado, el que desea avanzar rápidamente. Básicamente, es como usar git branch -f para mover la rama, excepto que también lo registra en el reflog como si realmente hicieras la fusión.

Por favor, por favor, no haga esto por algo que no sea un avance rápido, o simplemente reiniciará su sucursal a la otra confirmación. (Para verificar, ver si git merge-base <branch> <commit> da el SHA1 de la rama).