git pull
probablemente está creando el commit. Si realiza una confirmación local y luego se ejecuta git pull
despué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 --rebase
para evitar que esto suceda en el futuro, pero rebasar tiene sus peligros, y recomiendo evitarlos por pull
completo .
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 -p
descarga 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 -p
argumento elimina las ramas aguas arriba eliminadas. Por lo tanto, si la foo
rama se elimina en el origin
repositorio, git remote update -p
eliminará automáticamente su origin/foo
referencia.
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 -p
opció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 master
como 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 rebase
puede 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 --rebase
por 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 rebase
en 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 up
lugar 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 --rebase
es equivalente a correr git fetch
seguido 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 --rebase
no 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 -f
podría ser más apropiado que una llanura rebase
.
- No es (actualmente) posible pasar
--preserve-merges
a 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/master
si HEAD
es 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 up
y evitarlo por git pull
completo. Probablemente tendrá que usar reset
para deshacer la fusión creada por pull
y luego hacer git rebase -p @{u}
. El -p
argumento to git rebase
no ha funcionado de manera confiable para mí, por lo que podría tener que usar reset
para 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).