Git: cómo separar una twig de características después del hecho

¿Cómo puedo mover algunas confirmaciones de una característica desde una twig existente a una twig de características y eliminarlas efectivamente de la twig actual, como si la function se hubiera desarrollado en una twig de características separada?

Fondo: la twig develop contiene commits para dos características A (por ejemplo, 50 commits) y B (10 commits) wildly mixed, ya que originalmente deberían haber estado en la misma versión. Ahora estamos retrasando la característica B. Por lo tanto, queremos tener solo la característica A en la twig de develop , y una nueva twig de featureB que contiene los commits de A o A, B, de modo que si fusionamos ambas twigs, obtenemos la position actual de la twig de develop

Una forma de hacerlo sería crear la twig featureB desde la position actual de la twig de develop y luego aplicar de forma inversa los commits de A para develop . Pero entonces la fusión del nuevo develop y featureB sería simplemente A.

Otra forma sería cambiar el nombre del develop actual en featureB y seleccionar todas las confirmaciones de A en una nueva twig de develop . Pero eso efectivamente modificaría la historia del develop , lo cual es problemático.

¿Cuál es una mejor manera de hacer eso?

Si su twig de develop se ha publicado y no desea reescribir su historial (que sería la manera más fácil), entonces podría revertir sus cambios en el develop , iniciar una nueva twig B cambiar B cambios B featureB en el develop . Algo en la línea:

  #given history (top - newest) #shaA3 <-- develop, HEAD #shaB2 #shaA2 #shaB1 #shaA1 

revertir:

  git revert B2 git revert B1 

ahora la historia contiene:

  #revert of shaB1 <-- develop, HEAD #revert of shaB2 #shaA3 #shaB2 #shaA2 #shaB1 #shaA1 

crea featureB y vuelve a jugar commits revertidos de nuevo:

  git checkout -b featureB git rebase -i --onto develop shaB1~1 featureB 

Comente todas las confirmaciones, excepto las que pertenecen a la característica B ( shaB1 y shaB2 en nuestro caso) y complete la rebase. En este punto, debes tener el historial:

  #shaB2' <-- featureB, HEAD #shaB1' #revert of shaB1 <-- develop #revert of shaB2 #shaA3 #shaB2 #shaA2 #shaB1 #shaA1 

Para verificar que todo salió bien, puede hacer git diff shaA3 – debe estar vacío, git diff develop – debe contener todos los cambios B deseados.

PS: por supuesto, puede usar cherry-pick o revert de reversiones para reproducir los cambios b en branchB , en lugar de la rebase interactiva, por ejemplo, cuando se mantenga en desarrollo:

  git checkout -b branchB git revert <revert of shaB1> git revert <revert of shaB2> 

Te regalaré:

  #revert of revert of shaB2 = shaB2' <-- featureB, HEAD #revert of revert of shaB1 = shaB1' #revert of shaB1 <-- develop #revert of shaB2 #shaA3 #shaB2 #shaA2 #shaB1 #shaA1 

Con mucho, el método más limpio si puede administrarlo en absoluto es simplemente escribir los historiales correctos y cambiar de reference. Llamar a la base de la historia que desea dividir X ,

 git checkout -b new-develop X git cherry-pick [all the feature_A commits] # repeat the cherry-pick as needed or convenient if there's too many git checkout -b new-featureB X git cherry-pick [all the feature_B commits] # ... 

luego intercambie los nombres con git branch -m , force-push, y haga que todos vuelvan a ajustar y rebase cualquier trabajo no publicado según sea necesario.

Cualquier otra opción te dejará con una historia realmente desorderada, y no hay razón para infligir eso a toda la posteridad si es razonable evitarla. Evítelo si por alguna razón la comunicación es un problema.

Si realmente no puede hacer eso, entonces vea la respuesta muy detallada de @MykolaGurov .


( branchcheckout -b y checkout -b …)

Crear twig featureB desde el estado actual de develop. Código de compromiso para develop twig para cualquier desarrollo posterior de featureA. Confirmar código para ramificar featureB para desarrollo de featureB. Regularmente la function de twig de featureB contra la twig se develop para que tenga los cambios que se están agregando para el desarrollo de la característica A.

Si quiere evitar modificar el historial publicado de develop de sucursales, como en la respuesta de @thill , y también quiere evitar revertir las confirmaciones revertidas, como en la respuesta de @Mykola Gorov , también puede

  1. Crear twig featureB from develop
  2. Revertir las confirmaciones de la característica B en el develop sucursal. Puede ser sensato hacer esto en una única statement revert B , ya que esta es una operación en el historial.
  3. Merge branch se develop en featureB con ours estrategia. Esto no cambia ningún file en la featureB bifurcación featureB , sino que marca la confirmación revertida desde 2. como ya se fusionó en la function featureB Por lo tanto, si posteriormente fusionas la característica feature featureB nuevo en develop , el resultado ya no contendrá commit revert B

Al fusionar la característica featureB en el develop es posible que desee tener la function featureB como el primer padre de la confirmación. (Por ejemplo, se fusionan se develop en featureB y luego se establece develop to featureB , y no al revés.) Supongo que de esa manera la reversión ya no confundirá la culpa, etc. (?)