¿Por qué estoy fusionando "sucursal de seguimiento remoto 'origen / desarrollo' en desarrollo"?

125

Soy el único en mi organización que se compromete con el siguiente mensaje:

Combinar la rama de seguimiento remoto 'origen / desarrollo' en desarrollo

No estoy seguro de lo que estoy haciendo para causarlos, pero me gustaría parar.

¿Qué comando estoy emitiendo para crear este commit, y cuál es el comando apropiado que debo usar para no producirlo?

Jordan Feldstein
fuente
1
La respuesta hecha por Richard Hansen está bien. Pero creo que podría ser confuso para los principiantes. Mi solución es seguir haciendo pull --rebase pero para evitar el peligro, guardo mis cambios antes del pull. Luego, después de tirar, lo aplico. Resuelvo conflictos Finalmente puedo comprometerme y empujar.
Johnjohn
¿ git pull --autostash --rebaseFunciona para ti @Johnjohn?
fuentedelica

Respuestas:

206

git pullprobablemente está creando el commit. Si realiza una confirmación local y luego se ejecuta git pulldespués de que otra persona empuje una confirmación al repositorio, Git descarga la confirmación del otro desarrollador y luego la combina en su sucursal local.

Cómo evitar estos compromisos de fusión en el futuro

Podrías usar git pull --rebasepara evitar que esto suceda en el futuro, pero rebasar tiene sus peligros, y recomiendo evitarlos por pullcompleto .

En cambio, te animo a que sigas este patrón de uso:

# download the latest commits
git remote update -p

# update the local branch
git merge --ff-only @{u}

# if the above fails with a complaint that the local branch has
# diverged:
git rebase -p @{u}

Explicación

  • git remote update -pdescarga todas las confirmaciones en los repositorios remotos y actualiza las ramas de seguimiento remoto (por ejemplo, origin/master). NO toca su directorio de trabajo, índice o sucursales locales.

    El -pargumento elimina las ramas aguas arriba eliminadas. Por lo tanto, si la foorama se elimina en el originrepositorio, git remote update -peliminará automáticamente su origin/fooreferencia.

  • git merge --ff-only @{u}le dice a Git que combine la rama ascendente (el @{u}argumento) en su rama local, pero solo si su rama local puede ser "reenviada rápidamente" a la rama ascendente (en otras palabras, si no ha divergido).

  • git rebase -p @{u}mueve efectivamente las confirmaciones que ha realizado pero que aún no ha empujado en la parte superior de la rama ascendente, lo que elimina la necesidad de crear las confirmaciones de fusión tontas que está tratando de evitar. Esto mejora la linealidad del historial de desarrollo, lo que facilita su revisión.

    La -popción le dice a Git que conserve las fusiones. Esto evita que Git linealice las confirmaciones que se vuelven a modificar. Esto es importante si, por ejemplo, fusionó una rama de característica en master. Sin -p, cada commit en la rama de características se duplicaría mastercomo parte de la linealización realizada por git rebase. Esto haría que el historial de desarrollo sea más difícil de revisar, no más fácil.

    Cuidado : git rebasepuede que no haga lo que espera que haga, así que revise los resultados antes de presionar. Por ejemplo:

    git log --graph --oneline --decorate --date-order --color --boundary @{u}..
    

Prefiero este enfoque git pull --rebasepor las siguientes razones:

  • Le permite ver las confirmaciones ascendentes entrantes antes de modificar su historial para incorporarlas.
  • Le permite pasar la opción -p( --preserve-merges) git rebaseen caso de que necesite volver a crear una fusión intencional (por ejemplo, la fusión de una rama de característica ya insertada master).

Taquigrafía: en git uplugar degit pull

Para que sea más fácil hacer lo anterior, recomiendo crear un alias llamado up:

git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'

Ahora todo lo que necesita hacer para actualizar su sucursal es ejecutar:

git up

en lugar de git pull. Si obtiene un error porque su rama local se ha separado de la rama aguas arriba, esa es su señal para cambiar la base.

¿Por qué no git pull --rebase?

Correr git pull --rebasees equivalente a correr git fetchseguido de git rebase. Esto intenta avanzar rápidamente a los nuevos compromisos ascendentes, pero si eso no es posible, entonces cambiará sus compromisos locales en los nuevos compromisos ascendentes. Esto generalmente está bien, pero tenga cuidado:

  • Rebase es un tema avanzado, y debe comprender las implicaciones antes de volver a crear una nueva versión.
  • git pull --rebaseno le da la oportunidad de examinar los compromisos antes de incorporarlos. Dependiendo de lo que ha cambiado aguas arriba, es muy posible que rebase es la operación de un mal rebase --onto, merge, reset, o push -fpodría ser más apropiado que una llanura rebase.
  • No es (actualmente) posible pasar --preserve-mergesa la operación de rebase, por lo que cualquier fusión intencional de una rama de característica se linealizará, repitiendo (y por lo tanto duplicando) todas las confirmaciones de la rama de característica.

"Arreglando" una confirmación de fusión existente creada por git pull

Si aún no ha empujado un compromiso de fusión creado por git pull, puede cambiar el compromiso de fusión. Suponiendo que no ha realizado ninguna fusión intencional (p. Ej., Fusionando una rama de función ya insertada en su rama actual), lo siguiente debería hacerlo:

git rebase @{u}

El comando anterior le dice a Git que seleccione todas las confirmaciones que no sean de fusión accesibles desde HEAD(la confirmación actual), menos todas las confirmaciones accesibles desde @{u}(que es la abreviatura de "la rama ascendente", es decir, origin/mastersi HEADes master), reproducción (selección de cereza ) en la parte superior de la rama ascendente, y luego mueva la referencia de la rama actual para que apunte al resultado de reproducir las confirmaciones. Esto mueve efectivamente las confirmaciones sin fusión a la confirmación ascendente más reciente, lo que elimina la fusión creada por git pull.

Si tiene una confirmación de fusión intencional, no desea ejecutarla git rebase @{u}porque reproducirá todo desde la otra rama. Tratar este caso es sustancialmente más complicado, por lo que es bueno usarlo git upy evitarlo por git pullcompleto. Probablemente tendrá que usar resetpara deshacer la fusión creada por pully luego hacer git rebase -p @{u}. El -pargumento to git rebaseno ha funcionado de manera confiable para mí, por lo que podría tener que usar resetpara deshacer la fusión intencional, actualizar su sucursal local @{u}y luego rehacer la fusión intencional (lo cual es una molestia si hubiera mucha fusión peluda conflictos).

Richard Hansen
fuente
+1 para discutir --preserve-merges, excepto que en realidad no documentaste eso en los comandos que le dijiste que ejecutara, entonces -1 para eso.
Seth Robertson
@Seth: Gracias por el comentario; Actualicé la respuesta para recomendar -p. Evité recomendarlo antes porque no se necesita con mucha frecuencia y su comportamiento no está bien documentado.
Richard Hansen
3
¿Cuál es la diferencia entre git remote update -py git fetch?
Eckes
3
@eckes: git remote update -pes lo mismo que git fetch --all -p. Tengo la costumbre de usar git remote update -pcuando fetchno tenía la -popción.
Richard Hansen el
1
@ user1914692: Una vez que se complete la fusión, Git actualizará la rama local para que apunte a la confirmación de fusión recién creada, no a la misma confirmación que la rama remota. Este nuevo compromiso de fusión es el problema, especialmente cuando se empuja.
Richard Hansen
18
git fetch
git rebase origin/master

Deberias hacer eso. O si quieres seguir usando pull

git pull --rebase

También puede configurar esa bifurcación en su configuración para volver a crear un rebase automáticamente, o configurarse así automáticamente para cualquier otra bifurcación de seguimiento futura que realice. Entonces puedes volver a usar

git pull

Más sobre esto en la sección "pull with rebase en lugar de fusionar" de esta página:

http://mislav.uniqpath.com/2010/07/git-tips/

Adam Dymitruk
fuente