Git rebase y ramas infantiles

Resuelto Leonardo Alves Machado asked hace 7 años • 2 respuestas

Tengo la siguiente situación, en mi proyecto.

Master M1----M2----M3----M4----M5
                     \
                 Beta B1----B2----B3---B4
                                   \
                          Feature   F1---F2---F3

Estoy desarrollando en Feature, pero se lanzó una actualización realmente importante en el compromiso M5, y no quiero separarme Feature( B3depende Featurede B1y B2), y Betapuedo tener el cambio (no hay diferencia para Beta).

Si hago un git rebase Masteron Beta, solo movería la Betarama, ¿verdad (no se aplican cambios en Feature)? ¿O terminaría así (a continuación: los cambios también se aplicaron en Feature)?

Master M1----M2----M3----M4----M5
                                 \
                             Beta B1----B2----B3---B4
                                               \
                                      Feature   F1---F2---F3

Y, para quedar así (cambios aplicados el Feature), ¿qué debo hacer? Ese es mi estado deseado...

Leonardo Alves Machado avatar Jul 18 '17 04:07 Leonardo Alves Machado
Aceptado

Tienes razón: ejecutar git rebase Mastermientras está encendido Betano afectará Feature. (Aparte: ¿por qué las letras mayúsculas?)

La cuestión fundamental aquí es que git rebaselos "medios" copian algunas confirmaciones . El truco consiste en ver qué confirmaciones se copian, dónde y qué sucede con los nombres de las ramas después. Si las confirmaciones que se copiaron también son accesibles desde alguna otra rama, los originales (antes de copiarlos) siguen siendo accesibles desde esa otra rama.

Recuerde que todos los nombres de las ramas son meros punteros que apuntan a la confirmación más reciente de la rama. Todas las confirmaciones principales anteriores están en esa rama, incluso si esas confirmaciones anteriores también están en otras ramas. Entonces, "todas Betalas confirmaciones" incluyen M1inicialmente M3.

Entonces, ¿cómo git rebasesabe el primero que debe copiar solo B1 , B2, B3y B4? Creo que un elemento clave es dibujar el gráfico de forma un poco diferente:

M1----M2----M3----M4----M5   <-- Master
              \
               B1----B2----B3---B4   <-- Beta
                            \
                             F1---F2---F3   <-- Feature

Para ver qué se copiará, coloque un resaltador verde en la confirmación final de la rama, es decir, B4como lo señala Beta, y coloree todas las confirmaciones de verde a medida que sigue las líneas hacia la izquierda. Eso incluye confirmaciones M3y anteriores. Luego, lleva un resaltador rojo a la punta de confirmación Master(que es M5) y colorea todas las confirmaciones de rojo mientras sigues las líneas a la izquierda. El rojo sobrepinta el verde, por lo que M3los anteriores no se consideran para la copia. Esto deja exactamente el conjunto correcto de confirmaciones para copiar.

Las copias mismas llegan después del compromiso final del argumento. Es decir Master, las copias vienen después M5.

Después de que Git haga la copia, Git mueve el nombre Betapara que apunte a la copia de B4, a la que llamaremos B4'. Eso deja las Bnconfirmaciones originales pendientes... excepto que B3se puede acceder a ellas desde F1:

                          B1'---B2'---B3'--B4'   <-- Beta
                         /
M1----M2----M3----M4----M5   <-- Master
              \
               B1----B2----B3---B4   [no name]
                            \
                             F1---F2---F3   <-- Feature

Todo eso está bien para Beta, pero ahora le gustaría copiar Featurelas confirmaciones de . Si usted:

git checkout Feature
git rebase Beta

Git se coloreará F3de verde, luego F2y F1... pero luego volverá a marcar también B3en verde. B1Solo las copias B1' , B2', B3', B4'y las cinco Mconfirmaciones se colorean o se sobrescriben con rojo. Entonces Git copiará demasiadas confirmaciones.

La solución es utilizar git rebase --onto <name>. Agregar --ontole dice a Git dónde colocar las copias: quieres que vayan después de B4', por lo que puedes decir --onto Betaque las copias van después de Beta, es decir, B4'.

En realidad, eso no soluciona nada... todavía. Pero libera el otro argumento, el que iba Beta a ser, bueno, otra cosa.

Lo que quieres es decirle a Git dónde empezar a marcar las confirmaciones en rojo. Eso es B3, o si es más fácil B4,. Eso marcará B3y todas sus confirmaciones anteriores (incluidas M3las anteriores también) en rojo: no copiar.

Puede utilizar el ID sin formato de B3, si lo guarda. O puedes hacer que Git busque fácilmente el consejo anteriorBeta sobre el uso Beta@{1}:

git rebase --onto Beta Beta@{1}

Esto encuentra el ID de hash de la confirmación B4utilizando reflog para Beta.

torek avatar Jul 17 '2017 22:07 torek

En realidad terminaría con algo como esto:

Master M1----M2----M3----M4----M5
                    \            \
                     \       Beta B1----B2----B3---B4
                      \
                       \--B1'---B2'---B3'----F1---F2---F3
                                                       ^
                                                    feature

Básicamente, su rebase Betavolverá a aplicar las confirmaciones en Beta además del consejo actual de master. Sin embargo, las confirmaciones originales seguirán existiendo y si algo más, como otra rama, se refiere a esas confirmaciones, persistirán.

Primero necesitaría cambiar la base Betay luego cambiar la base featurepara mover todo "al lugar correcto".

Lasse V. Karlsen avatar Jul 17 '2017 21:07 Lasse V. Karlsen