Git push rechazado después de rebase de rama de función
Bien, pensé que este era un escenario simple de git, ¿qué me estoy perdiendo?
Tengo una master
sucursal y una feature
sucursal. Trabajo un poco master
, otro feature
y luego un poco más master
. Termino con algo como esto (el orden lexicográfico implica el orden de las confirmaciones):
A--B--C------F--G (master)
\
D--E (feature)
No tengo ningún problema en git push origin master
mantener el control remoto master
actualizado, ni git push origin feature
(cuando está activado feature
) en mantener una copia de seguridad remota de mi feature
trabajo. Hasta ahora estamos bien.
Pero ahora quiero rebasear feature
además de las F--G
confirmaciones en master, así que yo git checkout feature
y git rebase master
. Sigue bien. Ahora tenemos:
A--B--C------F--G (master)
\
D'--E' (feature)
Problema: en el momento en que quiero hacer una copia de seguridad de la nueva feature
rama rebasada git push origin feature
, el envío se rechaza ya que el árbol cambió debido a la rebase. Esto sólo se puede solucionar con git push --force origin feature
.
Odio consumir --force
sin estar seguro de que lo necesito. Entonces, ¿lo necesito? ¿El rebase implica necesariamente que el siguiente push
debería ser --force
completo?
Esta rama de funciones no se comparte con ningún otro desarrollador, por lo que no tengo ningún problema de facto con el force push, no voy a perder ningún dato, la pregunta es más conceptual.
El problema es que git push
se supone que la sucursal remota se puede reenviar rápidamente a su sucursal local, es decir, toda la diferencia entre las sucursales locales y remotas está en que la sucursal local tiene algunas confirmaciones nuevas al final como esta:
Z--X--R <- origin/some-branch (can be fast-forwarded to Y commit)
\
T--Y <- some-branch
Cuando realiza git rebase
confirmaciones, D y E se aplican a una nueva base y se crean nuevas confirmaciones. Eso significa que después de rebase tienes algo como esto:
A--B--C------F--G--D'--E' <- feature-branch
\
D--E <- origin/feature-branch
En esa situación, la sucursal remota no se puede reenviar rápidamente a la local. Sin embargo, en teoría, la sucursal local se puede fusionar con la remota (obviamente no la necesita en ese caso), pero como git push
solo realiza fusiones de avance rápido, arroja un error.
Y lo que --force
hace la opción es simplemente ignorar el estado de la rama remota y configurarla en la confirmación que está ingresando. Así que git push --force origin feature-branch
simplemente se anula origin/feature-branch
con local feature-branch
.
En mi opinión, cambiar la base de las ramas de características master
y forzarlas a regresar al repositorio remoto está bien siempre y cuando seas el único que trabaje en esa rama.
En lugar de usar -f
o --force
los desarrolladores deberían usar
--force-with-lease
¿Por qué? Porque comprueba la rama remota en busca de cambios, lo cual es absolutamente una buena idea. Imaginemos que James y Lisa están trabajando en la misma rama de funciones y Lisa ha impulsado un compromiso. James ahora cambia la base de su sucursal local y es rechazado cuando intenta presionar. Por supuesto, James cree que esto se debe a la rebase y los usos --force
y reescribiría todos los cambios de Lisa. Si James lo hubiera usado, --force-with-lease
habría recibido una advertencia de que hay confirmaciones realizadas por otra persona. No veo por qué alguien usaría --force
en lugar de --force-with-lease
al presionar después de una rebase.
En su lugar, usaría "checkout -b" y es más fácil de entender.
git checkout myFeature
git rebase master
git push origin --delete myFeature
git push origin myFeature
cuando eliminas, evitas insertar una rama saliente que contiene un SHA ID diferente. En este caso, solo estoy eliminando la rama remota.