Git: elimina las confirmaciones consecutivas que no son las confirmaciones más recientes y no comienzas desde la raíz

He revisado varias preguntas relacionadas sobre cómo aplastar las confirmaciones más recientes y aplastar una confirmación en la raíz , pero ninguna de ellas me ayudará a networkingucir las confirmaciones no recientes que no están en la raíz.

Aquí está mi escenario inicial:

D---E---F---G---H---I---J master 

y mi resultado deseado:

 D---E---Z---I---J master 

donde Z es la calabaza de F---G---H , y F---G---H , D---E e I---J pueden ser una secuencia arbitrariamente larga de compromisos no ramificados .

Primer enfoque:

 [lucas]/home/blah/$ git rebase -i D rebase in progress; onto D You are currently editing a commit while rebasing branch 'master' on 'D'. No changes You asked to amend the most recent commit, but doing so would make it empty. You can repeat your command with --allow-empty, or you can remove the commit entirely with "git reset HEAD^". Could not apply F... "Comments from commit F" [1]+ Done gitk [lucas]/home/blah/$ 

donde selecciono confirma que F---G---H es squash , mientras que abandona el commit más antiguo – la primera línea en la rebase interactiva – como pick . ¿Por qué esto no funciona?

Actualización: al final del command, una rebase está en progreso en D con E como el compromiso HEAD. Para estar seguro, no hubo una rebase en progreso al inicio y llamar a git rebase --abort mientras se ejecuta nuevamente tiene el mismo resultado. Cuando hago esto en la raíz, o HEAD, de acuerdo con los enlaces de arriba, todo funciona bien.

Segundo enfoque:

Hice otro bash [mediante la fusión de una nueva twig (última publicación en el foro)] [ http://git.661346.n2.nabble.com/Non-interactive-squash-a-range-td5251049.html ) que usa git checkout -b <clean-branch> <start-id> and git merge –squash `, pero obtengo lo siguiente:

 [lucas-ThinkPad-W520]/home/.../.Solstice_WS/7K_FGHF$ git checkout -b clean-branch D Switched to branch 'clean-branch' [lucas-ThinkPad-W520]/home/.../.Solstice_WS/7K_FGHF$ git merge --squash I Updating D..I Fast-forward Squash commit -- not updating HEAD .../GraphUtilities/impl/DAG.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) [lucas]/home/blah/$ git checkout master error: Your local changes to the following files would be overwritten by checkout: asdf/GraphUtilities//DAG.java Please, commit your changes or stash them before you can switch branches. Aborting 

que parece tener este resultado:

  ------------------- <clean-branch> with non-committed changes / D---E---F---G---H---I---J <master> 

Estoy un poco perplejo, así que ¿cómo puedo aplastar estos commits?

En última instancia, planeo implementar esto en JGit , por lo que una implementación de JGit sería aceptable.

NOTA

Puede haber un duplicado aquí , pero no tiene respuestas y creo que la pregunta no está clara.

ACTUALIZAR

Esto es en respuesta a la respuesta de @ ryenus a continuación:

La selección de cereza falla en el compromiso I2 , donde I2 está en I---I2---J Cuando falla, el estado de mi twig de work tiene D---E---Z , como estaba previsto hasta la selección de cereza, y es seguido por cambios no confirmados. Llamar a git cherry-pick --abort borra estos cambios no confirmados, y verifiqué que commit Z es correcto, que es la calabaza de F---G---H Después de cometer Z , y luego hacer una selección de cerezas, ¿por qué el pico de cereza falla en F ?

Parece como si git cherry-pick I...J intentara seleccionar a I2 , lo que crea el conflicto de fusión y falla. ¿Alguna sugerencia?

Aquí está mi resultado:

 [lucas]/home$ git checkout -b work H Switched to a new branch 'work' [lucas]/home$ git reset E Unstaged changes after reset: M adf/GraphUtilities//graph/impl/DAG.java [lucas]/home$ git commit -am "squashed commit here!" [work Z] squashed commit here! 1 file changed, 2 insertions(+), 5 deletions(-) [lucas]/home$ git cherry-pick I...J error: could not apply I2... <Comments from commit I2> hint: after resolving the conflicts, mark the corrected paths hint: with 'git add <paths>' or 'git rm <paths>' hint: and commit the result with 'git commit' [lucas]/home/$ git status On branch work You are currently cherry-picking commit I2. (fix conflicts and run "git cherry-pick --continue") (use "git cherry-pick --abort" to cancel the cherry-pick operation) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: 3b6863741967406c1888701eb139178187d429487b99787096441d67bed56/Gra phUtilities/src/edu/washington/cs/utils/graph/impl/DAG.java no changes added to commit (use "git add" and/or "git commit -a") [lucas]/home$ 

En primer lugar, si F---G---H son aplastados, entonces I---J sería I'---J' .

Teniendo en count eso, crearía una twig primero y luego git reset vanilla y luego el git cherry-pick :

 # D---E---F---G---H---I---J master 
  1. git checkout -b work H

    crear work sucursal en H

  2. git reset E

    ahora el work está en E

  3. git commit -am "FGH squeezed as Z"

    cometer los cambios hechos por F---G---H como Z

  4. git cherry-pick I^..J

    hacerse cargo de I---J

Ahora la twig de work está en la forma que desea, simplemente restablezca el master a ella:

 # D---E---Z---I`---J` work git checkout master git reset work git branch -d work 

Nota: el range de compromiso se ha corregido a I^..J , para representar la serie de compromiso I---J (de I a J , inclusive).