¿Cómo ayuda git a lidiar con el siguiente escenario?
Tengo una tarea dividida en 2 partes: tarea de fondo y tarea de interfaz. Realizo una solicitud de extracción para fusionar los cambios de back-end y espero a que se fusione (y responda a los comentarios). Mientras espero, realmente no puedo trabajar en los cambios frontend porque depende de los cambios de back-end y aún no están disponibles en la rama maestra.
¿Cuál es la mejor manera de incorporar los cambios a la rama de cambios frontend desde la rama de cambios del backend mientras aún se está revisando?
Respuestas:
También tengo este problema a veces. Git es muy flexible. Aquí hay una manera de hacerlo.
Su primera sucursal
featureA
está en revisión.Su segunda rama
featureB
está en desarrollo y depende del código en lafeatureA
rama.Fusiona la
featureA
rama con lafeatureB
rama.Si realiza cambios en la
featureA
rama, debe fusionar lafeatureA
rama en lafeatureB
rama nuevamente para incorporar los cambios.También debe asegurarse de fusionarse
featureA
en el tronco principal primero, de lo contrario, cuando se fusionefeatureB
en el tronco principal, también se fusionará inadvertidamentefeatureA
. Una vez quefeatureA
se haya fusionado con el tronco principal, puede deshacerse de lafeatureA
rama ya que ahorafeatureB
solo depende del tronco principal.Lo prefiero cuando mis ramas de características no dependen unas de otras, pero a veces lo hacen y hay que rodar con ellas.
fuente
featureA
sobrefeatureB
si es necesario?featureA
si tuviera que comenzar de nuevo. Es bueno pensar que las ramas de Git son desechables. Son baratos y fáciles, siempre puedes hacer una nueva sucursal. Incluso podría hacer una rama de prueba fuera de sufeatureB
rama si quisiera jugar con algo de lo que no estaba seguro, y luego desecharlo si no funcionó, o fusionarlo nuevamente en sufeatureB
rama si lo hizo.Espera, salta la fusión
Para este enfoque, usted no desea combinar su
feature_a
enfeature_b
repetidas ocasiones.Rebasar ha sido mencionado en otras respuestas, pero solo para rebatir cosas
master
. Lo que quiere hacer en su caso es:Comience
feature_b
desdefeature_a
, es decir:Cada vez que
feature_a
cambia mientras está esperando fusionarsemaster
, usted lo rebasefeature_b
:Finalmente, tan pronto como
feature_a
se haya fusionadomaster
, simplemente obtienes lo nuevomaster
y lo rebasasfeature_a
por última vez:Este rebase final injertará todos los commits que cuelgan del
feature_a
commit (que ahora es irrelevante ya que se ha fusionadomaster
) directamentemaster
. Sufeature_b
es ahora una rama simple y estándar que va directamente desdemaster
.EDITAR: inspirado en los comentarios, un poco de advertencia: si necesita hacer algún cambio que afecte a ambas características, asegúrese de hacerlo
feature_a
(y luego vuelva a redactar como se muestra). No lo haga en dos commits diferentes en ambas ramas, incluso si puede ser tentador; comofeature_a
es parte de la historia defeature_b
, tener el único cambio en dos confirmaciones diferentes será semánticamente incorrecto y posiblemente conducirá a conflictos o "resurrecciones" de código no deseado, más adelante.fuente
feature_a
varias ocasiones, es posible que más tarde se encuentre con problemas, cuandofeature_a
se haya rebaseado mientras tanto. Como resultado de la ejecucióngit checkout feature_b; git rebase feature_a
, puede obtener conflictos o algunas confirmaciones divertidas que contienen confirmaciones que revierten nuevos cambiosfeature_a
. Esto generalmente se puede resolver mediante el uso--interactive
y omitiendo los commits tomados de la versión anterior de la otra rama (tuve que hacer esto varias veces recientemente).rebase
que muchos más pasos individuales que un simplemerge
, seguramente hay una posibilidad visiblemente mayor de que cree conflictos; Por otro lado,merge
sería semánticamente bastante incorrecto hacerlo en este caso.merge
que tendría problemas similares o peores (un conflicto no es tan malo como entrar en un cambio no deseado). Veo una rama como una secuencia de cambios deseados precedidos por muchos cambios no relacionados (lógicamente pertenecientes a una rama diferente). Cuando repetidamente rebase con la misma rama, siempre elimino los cambios no relacionados, ya que sé que aparecerán de todos modos (posiblemente en una forma actualizada) y funciona bien.git rebase --onto
FTW: DYa tiene una rama de la que depende cada una de sus características, y que sigue cambiando. Se llama
master
.La forma típica para que una rama de características permanezca sincronizada
master
es mantenerse al tanto. Cuandomaster
cambia, normalmente estágit fetch origin master:master && git rebase master
en el directorio de trabajo de su sucursal.Puedes hacer lo mismo con otra rama de características: sigue buscándola y volviendo a marcarla encima.
Si, por alguna razón, necesita mover sus cambios a una rama diferente, puede seleccionar sus confirmaciones, que nunca se mezclan con las confirmaciones de otra rama.
fuente
feature-b
defeature-a
, y hacer un rebase el tiempo después de tiempo quefeature-a
está cambiando. Esta es una forma típica de hacer un gran cambio observable: dividirlo enpart-A
(basado enmaster
),part-B
(basado enpart-A
) y más si es necesario. Luego haga una solicitud de extracción para cada parte, y los revisores tienen más facilidad para mirar piezas más pequeñas agrupadas lógicamente.En este caso donde la tarea frontend tiene una dependencia crítica en el código de back-end, y desea comenzar a trabajar en el frontend antes de que el back-end se finalice y se acepte en master, simplemente comenzaría la tarea de front-end como una rama de características que sale del rama de back-end, en lugar de ramificar la interfaz en master.
Una rama de características que dure lo suficiente debe fusionarse en los cambios de maestro ocasionalmente (para asegurarse de que concilie cualquier fusión o conflictos semánticos como parte del trabajo de desarrollo en la rama de características, en lugar de como parte de la "revisión, qa, fusión- "dominar el proceso"). Entonces, lo hace en su rama de front-end, y cuando el trabajo de backend ha sido aceptado para dominar, obtendrá cualquier cambio menor que se haya realizado en el backend como parte de su revisión / aceptación automáticamente, por la misma ruta que usted obtenga cualquier otro cambio de código en el maestro.
Si resulta que la rama del backend necesita mucho más trabajo y continúa cambiando durante un período de tiempo antes de fusionarse con master (por ejemplo, si se encuentran problemas importantes durante la revisión), entonces probablemente desee realizar fusiones periódicas directamente desde la rama de back-end a la rama de front-end (para que no siga basando todo su trabajo de front-end en código de back-end obsoleto). Esto es fácil si eres el único desarrollador que realiza ambas funciones (ya que sabes si tú mismo realizas algún cambio importante), pero incluso si ambas características terminan siendo trabajadas en paralelo por diferentes desarrolladores, debería estar bien; solo tiene que mantenerse en comunicación (lo que necesitaría de todos modos, si está trabajando en tareas en paralelo donde una tiene una dependencia crítica de la otra).
Si resulta que toda la rama de back-end necesita ser abandonada y nunca se fusionará (parece que este sería un acuerdo bastante importante que rara vez sucedería), entonces debes elegir tus compromisos para una nueva rama que sale del maestro sin el trabajo de back-end, o aplica commits inversos que eliminan todo el código de back-end a la rama frontend. Pero como puedo ver, sería más probable que detuviera el trabajo de la interfaz hasta que descubriera qué iba a reemplazar el backend que está tirando y luego decida qué hacer.
fuente
No veo el problema aquí.
Ya tiene esto cada vez con su
master
sucursal, que sigue cambiando mientras se desarrollan y fusionan las características.Entonces, en su ejemplo concreto, primero crea la
feature_xxx_backend
rama y desarrolla los cambios de back-end. Cuando se hace esto, la sucursal está lista para revisión y se fusionarámaster
una vez que se complete la revisión.Por lo tanto, sólo tiene que iniciar otra rama,
feature_yyy_frontend
. Probablemente querrá ramificarse directamente desdefeature_xxx_backend
, para que tenga esos cambios ya en su sucursal. luego, simplemente desarrolle la función de interfaz como la ramamaster
.Cuando la
feature_xxx_backend
rama cambia, por ejemplo, porque hay cosas que surgen durante la revisión que deben abordarse, simplemente haga estos cambios y combínelos en lafeature_yyy_frontend
rama. Luego continúe en la rama frontend.Una vez que se completa la revisión de la rama back-end, se fusiona
master
. En este punto, sería aconsejable cambiar la base de lafeature_yyy_frontend
ramamaster
, de modo que los revisores solo necesiten revisar los nuevos cambios a los que contribuye esta ramamaster
, y no tengan que volver a revisar los cambios realizados para el backend (que ya han sido aprobados )Esto también se puede hacer cuando tiene dos, tres o más ramas dependientes. Si tiene dos ramas de características de las que depende, simplemente haga una rama derivada que tenga ambas características fusionadas. Rama desde allí, desarrolle la tercera característica, combine ambas ramas de características en el camino cuando cada una de ellas cambie. Cuando ambas características están hechas y se fusionan en la rama derivada, se vuelve a basar en eso, o si se fusionan en maestro, se vuelven a fusionar en maestro.
La reformulación (como se sugirió anteriormente) es realmente poderosa y ayuda a mantener un registro limpio de los cambios, lo que facilita mucho las revisiones.
fuente
Como mencionó Polygnome, en realidad puede fusionar su rama frontend con su rama backend en lugar de los maestros. Incluso con la configuración de sucursal actual que tiene ahora, simplemente puede hacer:
o simplemente
Sin embargo, tenga en cuenta que si no se aceptan los cambios del backend y se necesita más trabajo, deberá fusionar las actualizaciones del backend en la interfaz para evitar conflictos. Una vez que los cambios son aceptados en el maestro, puede volver a basar su interfaz en el maestro para deshacerse de los commits de fusión de back-end.
Técnicamente, también podría hacer todo con rebase, pero eso arruinará el historial de confirmaciones de su rama frontend. De donde vengo, esto se considera una mala práctica. YMMV
fuente
La mayoría de las respuestas aquí describen correctamente el proceso de combinar los cambios de la segunda rama a la primera, pero no abordan cómo minimizar la cantidad de conflictos que puede necesitar resolver.
Siempre que tenga dos conjuntos de grandes cambios que desee revisar individualmente (como
featureA
yfeatureB
), cree un RP que NO esté destinado a fusionarse, sino que obtenga comentarios tempranos sobre un PoC defeatureA
.Las personas podrán revisarlo rápidamente (es solo un PoC), y el objetivo es validar el diseño o enfoque general.
Luego, puede seguir trabajando en la función A, crear una solicitud de extracción y ramificar y trabajar en la función B.
La gran diferencia es que ahora puede esperar
featureA
que no cambie radicalmente: el diseño y el enfoque ya estaban validados. La revisión del código y los cambios requeridos pueden ser sutiles y locales en lugar de "fallas, necesita un enfoque diferente". Esto minimizará la cantidad de trabajo que necesita hacer para luego fusionarfeatureB
elfeatureA
código, independientemente del método que elija.fuente