git eliminar la confirmación de fusión del historial

97

Mi historial de Git se ve así:

Historia de Git

Me gustaría aplastar las confirmaciones moradas en una sola. No quiero volver a verlos en mi registro de confirmación.

Intenté hacer una git rebase -i 1, pero a pesar de que 1está en la rama azul (ver imagen), todavía veo cada confirmación en mi rama púrpura.

¿Cómo puedo eliminar por completo la rama púrpura (del registro de confirmación)?

Benjamín Toueg
fuente
¿Su repositorio se ha enviado a algún lugar que otras personas hayan extraído de él?
Schleis
Ambas ramas son puramente locales.
Benjamin Toueg

Respuestas:

100

Hacer git rebase -i <sha before the branches diverged>esto le permitirá eliminar la confirmación de fusión y el registro será una sola línea como desee. También puede eliminar las confirmaciones que ya no desee. La razón por la que su rebase no funcionaba era que no retrocedía lo suficiente.

ADVERTENCIA: Estás reescribiendo el historial haciendo esto. Hacer esto con cambios que se han enviado a un repositorio remoto provocará problemas. Recomiendo hacer esto solo con confirmaciones locales.

Schleis
fuente
4
Incluso si elijo un sha antes de que las ramas hayan divergido, veo todas las confirmaciones de la rama púrpura -_-
Benjamin Toueg
1
Sí, luego los eliminas en el editor que aparece git rebasey se eliminarán.
Schleis
4
Eliminar las confirmaciones resultó en la pérdida de todas las modificaciones de la fusión. Pero hice un restablecimiento parcial y pude tener algo bastante parecido a lo que quería (el orden no coincide con las expectativas iniciales).
Benjamin Toueg
2
esta respuesta está incompleta en detalle, ¿desde qué rama inicias el rebase?
grgry
3
Bastante seguro de que no desea "eliminar" las confirmaciones. 'eliminar' no es una opción en rebase, pero eliminar sí lo es. si elimina una confirmación, perderá los cambios que introdujo. Quieres aplastar las confirmaciones.
thecoshman
70

Comenzando con el repositorio en el estado original

Historia del repositorio original

Para eliminar la confirmación de fusión y aplastar la rama en una única confirmación en la línea principal

Compromisos aplastados, sin compromiso de fusión

Utilice estos comandos (reemplazando 5 y 1 con los SHA de las confirmaciones correspondientes):

git checkout 5
git reset --soft 1
git commit --amend -m '1 2 3 4 5'
git rebase HEAD master

Para retener un compromiso de fusión pero aplastar el compromiso de la rama en uno:

Confirmaciones aplastadas, confirmación de fusión retenida

Utilice estos comandos (reemplazando 5, 1 y C con los SHA de las confirmaciones correspondientes):

git checkout -b tempbranch 5
git reset --soft 1
git commit --amend -m '1 2 3 4 5'
git checkout C
git merge --no-ff tempbranch
git rebase HEAD master

Para eliminar la confirmación de fusión y reemplazarla con confirmaciones individuales de la rama

La rama se movió a la línea principal, sin compromiso de fusión

Solo hazlo (reemplazando 5 con el SHA de la confirmación correspondiente):

git rebase 5 master

Y finalmente, quitar la rama por completo

Rama eliminada por completo

Utilice este comando (reemplazando C y D con los SHA de las confirmaciones correspondientes):

git rebase --onto C D~ master
Allen Luce
fuente
en el git rebase 5 mastercaso, ¿por qué no es el orden "ABC 1 2 3 4 5 D ..."?
Roy
1
Ese comando toma las confirmaciones que masterno tienen en común con 5y las coloca encima de 5. El compromiso Cno es parte del linaje de 5, es el primero en ser movido encima de 5.
Allen Luce
2
Si quieres terminar con "ABC 1 2 3 4 5 D ..." puedes hacer:git rebase C 5; git rebase 5 master
Allen Luce
16

Hay dos formas de abordar esto según lo que desee:

Solución 1 : elimine las confirmaciones moradas, preservando el historial (en caso de que desee retroceder)

git revert -m 1 <SHA of merge>

-m 1 especifica qué línea principal elegir

Las confirmaciones púrpuras seguirán estando allí en el historial, pero como ha revertido, no verá el código de esas confirmaciones.


Solución 2 : elimine completamente las confirmaciones violetas (cambio disruptivo si se comparte el repositorio)

git rebase -i <SHA before branching out>

y elimine (elimine las líneas) correspondientes a las confirmaciones moradas.

Esto sería menos complicado si las confirmaciones no se hicieran después de la fusión. Las confirmaciones adicionales aumentan la posibilidad de conflictos durante revert/rebase.

prem
fuente
Esto no suena bien. Dejando de lado el hecho de que es difícil saber qué quería hacer el póster original con las confirmaciones moradas en primer lugar, si revierte la fusión, está bien, eso hará un parche inverso de los cambios de esa confirmación y lo agregará como otra confirmación, cancelando las confirmaciones moradas. Es como 1 - 1 = 0. Pero si luego reabastece las confirmaciones moradas, deja atrás el parche revertido, a menos que también lo reemplace. Si no lo hace, es como aplicar -1a su historial, no 0, así que dejará atrás los cambios que no desea.
@ Cupcake, siempre hubo dos respuestas separadas. He revisado la respuesta para que sea menos confusa: P
prem
AFAIK, esto no es lo que pide el OP. Quiere conservar los cambios, pero eliminar el ruido de su registro. Para eso, necesita aplastar las confirmaciones, eliminar eliminará los cambios.
thecoshman
Es cierto, parece que la pregunta original ha sido reformulada. Esta respuesta no es para el problema de los OP.
prem
16

Para eliminar simplemente una confirmación de fusión

Si todo lo que quiere hacer es eliminar un compromiso de fusión (2) para que sea como si nunca hubiera sucedido, el comando es simplemente el siguiente

git rebase --onto <sha of 1> <sha of 2> <blue branch>

Y ahora la rama violeta no está en absoluto en el registro de confirmación de azul y tienes dos ramas separadas nuevamente. A continuación, puede aplastar el morado de forma independiente y hacer cualquier otra manipulación que desee sin el compromiso de fusión en el camino.

Madriguera
fuente
De todas las respuestas, considero que esta es la más sencilla y la más fácil de hacer. Gracias.
Roshambo