¿Puedo reconfigurar de manera segura una twig en otra y luego dominarla?

Tengo que desarrollar twigs y encontré la twig B dependiendo del código de la twig A

Quiero volver a convertir A en B para poder seguir desarrollando B

Pronto, A se fusionará con el master (antes B ), pero no ahora. Entonces, cuando combine B , ¿romperá la reference de tener A re-basado en él?

¿Puedo volver a aplicar la base B en el master y todo estará bien o debo hacer un paso especial?

Tenga en count que git (y prácticamente todos los demás sistemas de control de versiones) llama a esta rebase a, no a.

De hecho, puede hacer este tipo de rebase. Sin embargo, es importante saber que cuando rebases algunos commit (s), git realmente los copy a commits nuevos . Esto afecta a todos los que comparten el código, si ya tienen los compromisos anteriores.

La image

Supongamos que lo que tienes ahora se puede dibujar de esta manera:

 ...--N--O--P--Q--R <-- master \ \ \ J--K <-- A \ E--F--G <-- B 

Aquí la ramificación A apunta a comprometer K , la ramificación B apunta a comprometer G y la ramificación a los puntos master para confirmar R (cada compromiso ahora tiene estos códigos de una letra para que podamos identificarlo más fácilmente, en realidad, sus nombres son SHA-1 hashes como bfcd84f529b... ). Los compromisos N a R son, por lo tanto, en el master (junto con todos los commits ocultos a la izquierda de N ); confirma N , O , P , J y K (y todos los commits a la izquierda de N como antes) están en la twig A ; y confirma N , E , F y G (y todos los commits a la izquierda de N como siempre) están en la twig B

Fusionar bases

Commit N es la base de fusión de las twigs B y master , y commit P es la base de combinación de las twigs A y master . La base de fusión es simplemente 1 el compromiso después del cual las twigs divergen, lo que se vuelve fácil de ver si dibujas el gráfico como acabamos de hacer. Esto es importante para la database de git rebase porque el método pnetworkingeterminado que usa git es encontrar esta combinación base de fusión y copyr las confirmaciones posteriores a ese punto. (Y, esto significa que antes de hacer una rebase, puede ser una buena idea dibujar el gráfico para que pueda ver lo que hará).

Copia de confirmaciones

Para copyr un solo compromiso, use el command git cherry-pick . No es necesario que haga esto ahora, rebase lo hará por usted, pero es una buena idea saber cómo funciona, así que vamos a cubrirlo brevemente.

En git, cada commit es una instantánea completamente autónoma. Por ejemplo, considere commit F en la twig B Commit F contiene el tree fuente completo asociado a su proyecto, desde el momento en que hizo commit F Esto también es cierto de commits E y G Si comparamos el compromiso E contra el compromiso F , veremos qué cambió entre "el tree para el compromiso E " y "el tree para el compromiso F ". De manera similar, si comparamos F vs G , descubriremos qué cambió al pasar de F a G

La conversión de un compromiso a un set de cambios, llamado set de cambios, nos permite copyr un compromiso. Supongamos, por ejemplo, que vemos lo que pasó de N a E Luego supongamos además que revisamos commit K y hacemos el mismo cambio , y luego lo confirmamos en una nueva twig temporal:

 ...--N--O--P--Q--R <-- master \ \ \ J--K <-- A \ \ \ E' <-- temp branch \ E--F--G <-- B 

Llamé al nuevo compromiso E' , en lugar de darle una nueva letra única, porque es una copy del compromiso E No es exactamente lo mismo que commit E por supuesto. Por un lado, tiene un padre diferente (tiene cometer K como su padre); y probablemente tenga un montón de otras diferencias de E : específicamente lo que sucedió en commits O , P , J y K , ya que ahora hemos aplicado "los cambios de N a E en" lo que estaba en K ".

Rebase es solo copys repetidas

git rebase funciona por:

  1. Identificando los commits para copyr;
  2. Copiándolos usando una twig temporal; y
  3. Re-apuntando la twig original.

Si seleccionas git checkout B y luego git rebase A , las confirmaciones identificadas en el paso 1 son aquellas después de la base de fusión entre B y A , hasta la punta de la twig B El A y el B aquí son porque tu twig actual es B y dijiste git rebase A

Ejercicio: observe el gráfico e identifique la combinación de B y A Puede ser un poco difícil de detectar, pero ¿y si volvemos a dibujar el gráfico de esta manera?

  Q--R <-- master / ...--N--O--P--J--K <-- A \ E--F--G <-- B 

(Este dibujo es, desde el punto de vista topológico, exactamente el mismo que el gráfico original que dibujamos, pero ahora es súper obvio que commit N es la base de fusión).

En resumen, estos son commits E , F y G Entonces rebase pasa al paso 2 y copy esos tres commits, colocando las copys después ("on") de la punta de la twig A (porque dijiste git rebase A ).

Por lo tanto, en este punto del process de rebase, ahora tenemos:

  Q--R <-- master / ...--N--O--P--J--K <-- A \ \ \ E'-F'-G' <-- temp \ E--F--G <-- B 

Solo hay una última cosa que debe hacer la rebase ahora, que es volver a apuntar la twig B actual, a la última confirmación que acaba de copyr. Eso es bastante fácil:

  Q--R <-- master / ...--N--O--P--J--K <-- A \ \ \ E'-F'-G' <-- B \ E--F--G [abandoned] 

Los commits originales, E a G , en su mayoría se han ido en este punto (todavía se retienen a través del reflog para la twig B pero a less que mires específicamente allí, ya no los verás). Las nuevas copys, E' a G' , se agregaron justo después de la punta de la twig A

Por qué todo esto importa

Toda esta copy y mezcla se realiza en su repository , y no en la copy de su repository. Esto significa que cualquier compañero de trabajo o server centralizado aún no tiene estas copys. Si git push las copys a un server centralizado, el server obtendrá las copys, pero si el server tenía las confirmaciones originales, ahora abandonadas, y si el server llamó a esa "twig B ", deberás presionar forzosamente para el server.

Al hacer este empuje de fuerza, el server descartará sus copys de las confirmaciones originales, y colocará las confirmaciones copydas y las llamará "twig B ". Esto es cierto incluso si , en el server, hay una confirmación H posterior a la confirmación G , con la twig B apuntando a confirmar H En otras palabras, esto puede "perder" confirmaciones del server. Esa es la primera arruga: debe coordinar con todos los demás que utilizan el server, para que no pierda compromisos.

Además, después de hacer un esfuerzo de fuerza y ​​/ o si sus compañeros de trabajo comparten su repository (obteniendo o extrayendo de él), es posible que sus compañeros de trabajo tengan que ajustar sus repositorys para dar count de la copy-confirma-y-muévase -branch-label. Para ellos, esta es una rebase aguas arriba y deben recuperarse de ella . Esta es la segunda arruga: debe coordinarse con todos los demás que utilizan la twig, para que sepan que se recuperan de la rebase ascendente.

En resumen, asegúrese de que todos sus codesarrolladores estén de acuerdo con esto.

Si tiene otras personas que trabajan con usted y comparten las sucursales, tendrá que volver a establecer la base, solo asegúrese de que todos lo sepan. Si estas confirmaciones de que volverá a establecer una database no se publicarán (si son solo privadas para su propio repository), esta coordinación no requiere ningún esfuerzo, ya que no hay nadie más a quien informar, por lo que no hay nadie que pueda oponerse .

Fusionando, y tal vez rebase de nuevo

Pronto, A se fusionará con el master (antes B ), pero no ahora. Entonces, cuando combine B , ¿romperá la reference de tener A re-basado en él?

Nuevamente, la manera de responder estas preguntas es comenzar por dibujar el gráfico de compromiso. Usemos el dibujo nuevo y reestablecido, luego agreguemos la combinación de fusión que fusiona B en master . Como queremos mostrar la fusión, necesitamos volver a dibujar el gráfico un poco una vez más, para que sea más fácil conectar las filas:

 ...--N--O--PQR <-- master \ J--K <-- A \ E'-F'-G' <-- B 

Ahora ejecutaremos git checkout master y git merge A para realizar una nueva combinación de commit M :

 ...--N--O--PQR--M <-- master \ / J--K <-- A \ E'-F'-G' <-- B 

No hemos tenido que cambiar nada en B aquí, y podemos seguir desarrollándolo como siempre. Pero, si queremos , y si todos nuestros co-desarrolladores están de acuerdo, ahora podemos volver a establecer la base B , esta vez en master .

Si hacemos el git checkout B; git rebase master git checkout B; git rebase master , la rebase , como de costumbre, comenzará por encontrar la base de combinación entre B y master . ¿Cuál es la base de fusión? Mira el gráfico y encuentra el punto donde el master y B unen. Definitivamente no es la nueva combinación de commit M , pero tampoco es N tampoco.

Los commits que están en la twig B son N , O , P , J , K , E' , F' y G' (y cualquier compromiso que no podamos ver que esté a la izquierda de N ). Esta parte es bastante simple. La parte complicada son las confirmaciones que se encuentran en el master sucursal. Estos son N , O , P , Q , R y M , pero también J y K Esto se debe a que se pueden alcanzar esos dos commits siguiendo al segundo padre de commit M

Por lo tanto, la base de combinación, que se define como la confirmación "más cercana" que está en ambas twigs, es en realidad cometer K ¡Esto es exactamente lo que queremos! Para reubicar B en master , queremos que git copie E' , F' y G' . Las nuevas copys E'' , F'' y G'' irán después de M , y obtendremos esto:

  E''-F''-G'' <-- B / ...--N--O--PQR--M <-- master \ / J--K <-- A \ E'-F'-G' [abandoned] 

La verdadera lección aquí es dibujar el gráfico, ya que te ayudará a descubrir qué está pasando.


1 Por lo less, es simple cuando hay un solo punto. En charts más complejos, puede haber más de una base de combinación. Sin embargo, volver a establecer bases de datos con charts complejos requiere mucho más de lo que puedo escribir en esta publicación de SO en particular.