OK, pensé que este era un simple escenario git, ¿qué me estoy perdiendo?
Tengo una master
rama y una feature
rama. Realizo algunos trabajos master
, otros feature
, y luego otros master
. Termino con algo como esto (el orden lexicográfico implica el orden de los commits):
A--B--C------F--G (master)
\
D--E (feature)
No tengo ningún problema para git push origin master
mantener master
actualizado el control remoto , ni con git push origin feature
(cuando está activado feature
) para mantener una copia de seguridad remota para mi feature
trabajo. Hasta ahora, estamos bien.
Pero ahora quiero hacer una nueva base feature
sobre los F--G
commits 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 bifurcación feature
ramificada git push origin feature
, el empuje se rechaza ya que el árbol ha cambiado debido a la rebase. Esto solo se puede resolver con git push --force origin feature
.
Odio usar --force
sin estar seguro de que lo necesito. Entonces, ¿lo necesito? ¿El rebase implica necesariamente que el próximo push
debe ser --force
completo?
Esta rama de características no se comparte con ningún otro desarrollador, por lo que no tengo ningún problema de facto con el empuje de fuerza, no voy a perder ningún dato, la pregunta es más conceptual.
git pull feature-branch
, esta extracción generará una nueva confirmación de fusión (al fusionar versiones remotas y locales de la rama de características). Entonces, o obtienes una fusión innecesaria después de rebase, o presionas--force
.push --force
lo tanto, no es un problema) para mantener el historial de commits lineal sin ningún commit de fusión.--force-with-lease
como @hardev sugerido es una gran opciónEn lugar de usar -f o --force los desarrolladores deberían usar
¿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 características y Lisa ha empujado una confirmación. James ahora rebasa su rama local y es rechazado cuando intenta presionar. Por supuesto, James piensa que esto se debe a un rebase y usa --force y volvería a escribir todos los cambios de Lisa. Si James hubiera usado la fuerza con arrendamiento, habría recibido una advertencia de que alguien más ha cometido compromisos. No veo por qué alguien usaría --force en lugar de --force-with-lease al presionar después de un rebase.
fuente
git push --force-with-lease
me ha ahorrado un montón--force-with-lease
aborda la preocupación de usar--force
En su lugar, usaría "checkout -b" y es más fácil de entender.
cuando eliminas, evitas empujar una rama existente que contiene una ID de SHA diferente. Solo estoy borrando la rama remota en este caso.
fuente
push --force
, por lo que es solo una forma de evitar un repositorio git evitando--force
. Como tal, no creo que sea una buena idea, ya sea que el repositorio lo permitapush --force
, o por una buena razón lo deshabilita. La respuesta de Nabi es más apropiada si--force
está deshabilitada en el repositorio remoto, ya que no tiene el riesgo de perder confirmaciones de otros desarrolladores o causar problemas.Una solución a esto es hacer lo que hace el script de fusión de rebase de msysGit : después del rebase, fusionarse en el antiguo encabezado de
feature
with-s ours
. Terminas con el gráfico de confirmación:... y tu impulso
feature
será un avance rápido.En otras palabras, puedes hacer:
(No probado, pero creo que es correcto ...)
fuente
git rebase
(en lugar de fusionarsemaster
nuevamente en su rama de características) es hacer un historial de confirmaciones lineales limpias. Con su enfoque, la historia empeora aún más. Y como el rebase crea nuevas confirmaciones sin ninguna referencia a sus versiones anteriores, ni siquiera estoy seguro de que el resultado de esta fusión sea adecuado.merge -s ours
es que agrega artificialmente una referencia principal a la versión anterior. Claro, la historia no parece limpia, pero el interlocutor parece estar particularmente molesto por tener que forzar el empuje de lafeature
rama, y esto lo evita. Si quieres hacer una nueva versión, es más o menos uno u otro. :) En general, creo que es interesante que el proyecto msysgit haga esto ...ours
estrategias antes, pero pensé que se aplicaban solo a situaciones de conflicto resolviéndolas automáticamente usando cambios en nuestra sucursal. Resultó que funciona de manera diferente. Y trabajar de esa manera es muy útil si necesita una versión modificada (p. Ej., Para que el mantenedor de repositorios la aplique limpiamentemaster
) pero desea evitar forzar la presión (si muchas otras personas por alguna razón están usando su rama de características).Puede ser o no el caso de que solo haya un desarrollador en esta rama, que ahora (después de la modificación) no está en línea con el origen / característica.
Como tal, sugeriría usar la siguiente secuencia:
Sí, nueva rama, esto debería resolver esto sin una fuerza, lo que creo que generalmente es un gran inconveniente.
fuente
Mi forma de evitar el empuje de la fuerza es crear una nueva rama y continuar trabajando en esa nueva rama y, después de un poco de estabilidad, eliminar la vieja rama que se volvió a armar:
fuente
Otros han respondido tu pregunta. Si rebasas una rama, tendrás que forzarla a empujar esa rama.
Rebase y un repositorio compartido generalmente no se llevan bien. Esto es reescribir la historia. Si otros están usando esa rama o se han bifurcado de esa rama, entonces el rebase será bastante desagradable.
En general, rebase funciona bien para la administración de sucursales locales. La administración remota de sucursales funciona mejor con fusiones explícitas (--no-ff).
También evitamos fusionar master en una rama de características. En su lugar, cambiamos a maestro pero con un nuevo nombre de rama (por ejemplo, agregando un sufijo de versión). Esto evita el problema de rebase en el repositorio compartido.
fuente
¿Qué hay de malo con un
git merge master
en lafeature
rama? Esto preservará el trabajo que tenía, mientras lo mantiene separado de la rama principal.Editar: Ah, lo siento, no leí tu declaración de problema. Necesitará fuerza mientras realiza a
rebase
. Todos los comandos que modifican el historial necesitarán el--force
argumento. Esto es a prueba de fallas para evitar que pierda el trabajo (lo antiguoD
yE
lo que se perdería).Así que realizó una
git rebase
que hizo que el árbol se vea (aunque parcialmente oculto comoD
yE
ya no está en una rama con nombre):Entonces, al tratar de impulsar su nueva
feature
rama (conD'
yE'
dentro de ella), perderíaD
yE
.fuente
Para mí, seguir pasos sencillos funciona:
Después de hacer todo lo anterior, también podemos eliminar la rama myFeature siguiendo el comando:
fuente
Lo siguiente funciona para mí:
git push -f origin branch_name
y no elimina ninguno de mi código.
Pero, si desea evitar esto, puede hacer lo siguiente:
entonces puedes elegir todos tus commits para la nueva sucursal.
git cherry-pick COMMIT ID
y luego empuje su nueva rama.fuente
-f
es un alias para--force
, que es lo que la pregunta intenta evitar si es posible.Como el OP entiende el problema, solo busca una solución más agradable ...
¿Qué tal esto como práctica?
Tenga una rama de desarrollo de características real (donde nunca rebase y fuerce, para que sus compañeros desarrolladores de características no lo odien). Aquí, regularmente toma esos cambios de main con una fusión. Una historia más desordenada , sí, pero la vida es fácil y nadie se interrumpe en su trabajo.
Tenga una segunda rama de desarrollo de características, donde un miembro del equipo de características regularmente empuja todos los compromisos de características a, de hecho rebase, de hecho forzado. De manera casi limpia basada en un compromiso maestro bastante reciente. Una vez completada la función, empuje esa rama encima del maestro.
Es posible que ya haya un nombre de patrón para este método.
fuente