Usamos git y tenemos una rama maestra y ramas de desarrollo. Necesito agregar una nueva característica y luego volver a crear los commits en master, luego empujar master al servidor CI.
El problema es que si tengo conflictos durante el rebase no puedo pasar a mi rama de desarrollador remoto (en Github) después de que se complete el rebase, hasta que retire mi rama remota. Esto provoca confirmaciones duplicadas. Cuando no hay conflictos, funciona como se esperaba.
pregunta: después de la resolución de conflictos y rebase, ¿cómo sincronizo mis ramas de desarrollador local y remoto sin crear confirmaciones duplicadas?
Preparar:
// master branch is the main branch
git checkout master
git checkout -b myNewFeature
// I will work on this at work and at home
git push origin myNewFeature
// work work work on myNewFeature
// master branch has been updated and will conflict with myNewFeature
git pull --rebase origin master
// we have conflicts
// solve conflict
git rebase --continue
//repeat until rebase is complete
git push origin myNewFeature
//ERROR
error: failed to push some refs to '[email protected]:ariklevy/dropLocker.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
// do what git says and pull
git pull origin myNewFeature
git push origin myNewFeature
// Now I have duplicate commits on the remote branch myNewFeature
EDITAR
Parece que esto interrumpirá el flujo de trabajo:
developer1 trabajando en myNewFeature developer2 trabajando en hisNewFeature ambos usan master como rama principal
developer2 combina myNewFeature en hisNewFeature
developer1 vuelve a redactar, resuelve conflictos y luego fuerza los empujes a la rama remota para myNewFeature
un par de días después, developer2, fusiona myNewFeature en suNewFeature nuevamente
¿Esto hará que los otros desarrolladores odien el desarrollador1?
we
? ¿Estás en un equipo de más que solo tú?they
diga (las personas que saben más que yo) que si comparte su código, entonces no debería estar usandorebase
. ¿Por qué no estás haciendogit pull
ygit merge
?force
el empuje)rewriting history
, eso es unrebase
Respuestas:
Primero, usted y aquellos con los que está trabajando deben acordar si una rama de tema / desarrollo es para desarrollo compartido o solo para usted. Otros desarrolladores saben que no deben fusionarse en mis ramas de desarrollo porque serán modificadas en cualquier momento. Por lo general, el flujo de trabajo es el siguiente:
Luego, para mantenerme actualizado con el control remoto, haré lo siguiente:
Hago esto por dos razones. Primero porque me permite ver si hay cambios remotos sin necesidad de cambiar de mi rama de desarrollo. En segundo lugar, es un mecanismo de seguridad para asegurarse de no sobrescribir ningún cambio no guardado / confirmado. Además, si no puedo avanzar rápidamente a la fusión con la rama maestra, eso significa que alguien ha cambiado el nombre del maestro remoto (por lo que deben ser azotados severamente) o accidentalmente me comprometí con el maestro y necesito limpiar mi extremo.
Luego, cuando el control remoto haya cambiado y lo haya enviado rápidamente a la última versión, volveré a redactar:
Otros desarrolladores entonces saben que necesitarán volver a crear sus ramas de desarrollo en mi último:
Lo que resulta en una historia mucho más limpia:
No combine los compromisos de ida y vuelta a su antojo. No solo crea confirmaciones duplicadas y hace que el historial sea imposible de seguir, sino que encontrar regresiones de un cambio específico se vuelve casi imposible (por eso estás usando el control de versiones en primer lugar, ¿verdad?). El problema que tienes es el resultado de hacer esto.
También parece que otros desarrolladores pueden estar comprometiéndose con sus ramas de desarrollo. ¿Puedes confirmar esto?
El único momento para fusionarse es cuando la rama de su tema está lista para ser aceptada
master
.En otros comentarios. Si varios desarrolladores se comprometen con el mismo repositorio, todos deberían considerar tener ramas con nombre para distinguir entre las ramas de desarrollo de desarrolladores. Por ejemplo:
Por lo tanto, todas las ramas temáticas de los desarrolladores residen dentro de su propio conjunto anidado.
fuente
--force
bandera cuando lo hacesgit push -f origin devel0
?git push
no puede avanzar rápidamente (es decir, el historial de sha no coincide), debe forzar la pulsación para sobrescribir el historial anterior con el nuevo historial generado a partir degit rebase
.Debe forzar el empuje ya que ha movido las confirmaciones más abajo de la línea, git espera que agregue confirmaciones a la punta de la rama.
git push -f origin myNewFeature
Arreglará tu problema.Consejo: Arriba hay un uso legítimo de empuje forzado. Nunca reescribas la historia en un repositorio de acceso público o mucha gente te odiará.
fuente
git push --force-with-lease
es mucho más seguro que usargit push --force
git push --force-with-lease origin HEAD
- suponiendo que su sucursal objetivo ya estéLo principal a tener en cuenta aquí es lo que están haciendo pull y rebase detrás de escena.
Un tirón básicamente hará dos cosas: buscar y fusionar. Cuando incluye --rebase, hará una nueva versión en lugar de la fusión.
Un rebase es más o menos como esconder todos sus cambios locales desde que se bifurcó, reenviando rápidamente su rama al último commit en el objetivo y desarmando sus cambios en orden en la parte superior.
(Esto explica por qué puede obtener múltiples avisos de resolución de conflictos al hacer un rebase versus la única resolución de conflicto que puede obtener con una fusión. Tiene la oportunidad de resolver un conflicto en CADA confirmación que se está rebase para preservar sus confirmaciones. )
Nunca deseará impulsar cambios modificados a ramas remotas, ya que esto está reescribiendo el historial. Por supuesto, nunca es un poco fuerte, ya que casi siempre hay excepciones. El caso de que necesite mantener una versión remota de su repositorio local para trabajar en un entorno específico, por ejemplo.
Esto requerirá que empuje los cambios de base a veces usando la fuerza:
O, en algunos casos, su administrador puede haber eliminado la capacidad de forzar, por lo que debe eliminar y volver a crear:
En cualquier caso, debe estar absolutamente seguro de saber lo que está haciendo si alguien más está colaborando con usted en su sucursal remota. Esto puede significar que trabajas en conjunto inicialmente con fusiones y vueltas a unir en un formato de confirmación más manejable justo antes de ir a master y eliminar tu rama de trabajo.
Recuerde que casi siempre puede recurrir al GC de git aprovechando:
Este es un GRAN salvavidas, ya que puede restablecerlo a un estado más estable si se pierde en toda su gestión de rebase / conflicto.
fuente
Necesita realizar un empuje forzado, es decir
git push -f origin myNewFeature
Ah, y es mejor que te asegures de que las personas no basen nada en tu rama de desarrollo; por lo general, no se supone que publiques ramas en las que estás reescribiendo el historial (o más bien no reescribes el historial una vez publicado). Una forma sería usar un nombre de sucursal como
wip/myNewFeature
y luego mencionar que laswip
sucursales serán modificadas para dominar de vez en cuando.fuente
git push --force-with-lease
es mucho más seguro que usargit push --force
-f
para un empuje forzado normal :)La respuesta general que ya se ha dado, para usar
git push -f origin myNewFeature
cuando se empujan cambios modificados, es un buen punto de partida. Estoy escribiendo esta respuesta para abordar la edición sobre si interrumpirá su flujo de trabajo.Si suponemos que se va a utilizar
git pull --rebase ...
(o alguna variación sobre el mismo), seguido de una fuerza de empuje para la rama remota, a continuación, lo que rompe el flujo de trabajo en su ejemplo se Developer2 está fusionandomyNewFeature
enhisNewFeature
. Tiene sentido poder cambiar la base de su propia rama de características siempre que nadie más esté trabajando en esa rama, por lo que necesita reglas para delimitar el territorio de la rama.Puede evitar esto mediante a) establecer una regla de la que solo se fusiona
master
, ob) crear unadevelop
rama colectiva , en la que basará su propiamyNewFeature
rama, y establecer una regla de la que solo se fusionarádevelop
.master
luego se reservará solo para hitos o lanzamientos (o como quiera que quiera configurarlo), ydevelop
será donde presione cada función cuando esté lista para integrarse en otras ramas de funciones.Creo que esto podría considerarse una versión simplificada del flujo de trabajo de Gitflow.
fuente
Estoy de acuerdo con MrCholo , y tal vez Trevor Norris podría considerar actualizar su buena respuesta para reemplazar
con
fuente