Git rebase y ramas infantiles
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
( B3
depende Feature
de B1
y B2
), y Beta
puedo tener el cambio (no hay diferencia para Beta
).
Si hago un git rebase Master
on Beta
, solo movería la Beta
rama, ¿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...
Tienes razón: ejecutar git rebase Master
mientras está encendido Beta
no afectará Feature
. (Aparte: ¿por qué las letras mayúsculas?)
La cuestión fundamental aquí es que git rebase
los "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 Beta
las confirmaciones" incluyen M1
inicialmente M3
.
Entonces, ¿cómo git rebase
sabe el primero que debe copiar solo B1
, B2
, B3
y 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, B4
como lo señala Beta
, y coloree todas las confirmaciones de verde a medida que sigue las líneas hacia la izquierda. Eso incluye confirmaciones M3
y 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 M3
los 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 Beta
para que apunte a la copia de B4
, a la que llamaremos B4'
. Eso deja las Bn
confirmaciones originales pendientes... excepto que B3
se 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 Feature
las confirmaciones de . Si usted:
git checkout Feature
git rebase Beta
Git se coloreará F3
de verde, luego F2
y F1
... pero luego volverá a marcar también B3
en verde. B1
Solo las copias B1'
, B2'
, B3'
, B4'
y las cinco M
confirmaciones se colorean o se sobrescriben con rojo. Entonces Git copiará demasiadas confirmaciones.
La solución es utilizar git rebase --onto <name>
. Agregar --onto
le dice a Git dónde colocar las copias: quieres que vayan después de B4'
, por lo que puedes decir --onto Beta
que 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á B3
y todas sus confirmaciones anteriores (incluidas M3
las 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 B4
utilizando reflog para Beta
.
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 Beta
volverá 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 Beta
y luego cambiar la base feature
para mover todo "al lugar correcto".