Revertir una fusión de git, y luego fusionar algunas de las confirmaciones revertidas

Supongamos el siguiente historial de git (en order cronológico):

master [I]------------------------[M2]---[MG]---[RV]---[MG2] dev \---[D1]----------[D2]----------/ / release \---[R1]-------------------------------/ 
  • El repository comienza con un compromiso inicial I
  • Una twig de desarrollo se crea con un nuevo compromiso D1 .
  • Una twig de lanzamiento se bifurca fuera de dev con una nueva confirmación R1 .
  • Se agrega una nueva confirmación a la twig de desarrollo ( D2 ).
  • Se agrega una nueva confirmación a la twig maestra ( M2 ).
  • dev se fusiona en master ( MG )
  • ¡UH oh! no teníamos intención de hacer eso … revertimos la fusión comprometer RV con -m 1 para especificar que el maestro debe considerarse la línea principal
  • Tuvimos la intención de fusionar la versión en master, por lo que hacemos eso ahora ( MG2 )

¡Oh no! Ahora los cambios introducidos en D1 no están presentes en el maestro. Quiero que estén incluidos (pero no quiero que los cambios de D2 estén presentes). Entonces mis preguntas son:

  1. Asumiendo que acabo de fusionar dev to master ( MG ), ¿hay algún command que pueda usar en lugar de git revert para que cuando fusione la versión en master sigo teniendo los cambios de D1 ?
  2. Supongamos que ya he avanzado con una fusión de dev en master y revert, ¿hay algún command que pueda usar en lugar de git merge para que cuando fusione la versión en master sigo teniendo los cambios de D1 ?

Soy consciente de que podría lograrlo haciendo un git reset --hard M2 en la twig principal, pero quiero evitar volver a escribir el historial si es posible. También sería genial si una solución representara la posibilidad de que se añadieran confirmaciones "buenas" adicionales a la twig maestra entre MG y RV o entre RV y MG2 .

La solución propuesta aquí (búsqueda de ADDENDUM) es recrear una alternativa a D1 ( D1' continuación), de modo que su contenido no sea ignorado por fusiones posteriores:

 git checkout dev git rebase --no-ff I 

Esto debería resultar en:

 dev /---[D1']---------[D2'] master [I]------------------------[M2]---[MG]---[RV]---[MG2] \---[D1]----------[D2]----------/ / release \---[R1]-------------------------------/ 

También necesita recrear su twig de release para que comience en D1' , luego combinarla para dominar:

 git checkout release git rebase D1' git checkout master git merge release 

Resultado:

 release /---[R1']---------------------------------\ dev /---[D1']---------[D2'] \ master [I]------------------------[M2]---[MG]--[RV]--[MG2]--[MG3] \---[D1]----------[D2]----------/ / \---[R1]-----------------------------/ 

Por supuesto, si no ha presionado MG2 , podría ser una buena idea limpiar antes. Este tipo de historia podría confundir fácilmente a las personas en el futuro.

Creo que puedes usar git cherry-pick para resolver tus errores> https://git-scm.com/docs/git-cherry-pick