¿Cómo aplastar mis últimos x commits juntos?

9 minutos de lectura

avatar de usuario
marcadorison

¿Cómo puedo agrupar mis últimas X confirmaciones en una sola confirmación usando Git?

  • Relacionado: Git: combinación de varias confirmaciones antes de enviar.

    usuario456814

    6 de junio de 2014 a las 8:07

  • Para aplastar hasta EL primer compromiso, vea esto: stackoverflow.com/questions/1657017/…

    – goelakash

    6 de marzo de 2016 a las 13:26

  • post squash hay que hacer forzar push stackoverflow.com/questions/10298291/…

    – vikramvi

    14 de julio de 2016 a las 13:04

  • Además de las respuestas publicadas, los clientes de GUI pueden hacer esto fácilmente. Puedo aplastar docenas de confirmaciones en GitKraken con solo cuatro clics.

    – Aarón Franke

    14 de enero de 2019 a las 12:56

avatar de usuario
anomia

Usar git rebase -i <after-this-commit> y reemplace “pick” en la segunda y posteriores confirmaciones con “squash” o “fixup”, como se describe en el manual.

En este ejemplo, <after-this-commit> es el hash SHA1 o la ubicación relativa del HEAD de la rama actual desde la que se analizan las confirmaciones para el comando rebase. Por ejemplo, si el usuario desea ver 5 confirmaciones del HEAD actual en el pasado, el comando es git rebase -i HEAD~5.

  • Qué quiere decir <after-this-commit>?

    – 2540625

    4 de noviembre de 2014 a las 5:49

  • <after-this-commit> es confirmación X+1, es decir, padre de la confirmación más antigua que desea aplastar.

    – joozek

    4 de noviembre de 2014 a las 12:04

  • Si ya ha enviado las confirmaciones, deberá presionar -f para mover a la fuerza la rama remota a su nueva confirmación. Sin embargo, esto molestará a cualquiera que esté trabajando sobre las confirmaciones anteriores.

    – interfiere

    08/12/2014 a las 18:31

  • La diferencia entre este rebase -i acercamiento y reset --soft es, rebase -ime permite conservar el autor de la confirmación, mientras que reset --soft me permite volver a comprometerme. A veces necesito aplastar las confirmaciones de las solicitudes de extracción y mantener la información del autor. A veces necesito reiniciar el software en mis propios compromisos. Upvotes a ambas grandes respuestas de todos modos.

    – zionyx

    15 de septiembre de 2015 a las 9:31


  • Use git rebase -i <after-this-commit> and replace "pick" on the second and subsequent commits with "squash" or "fixup", as described in the manual. uhhhh… ¿qué?

    – Queso

    27 de julio de 2016 a las 3:18

  • @Mark Amery: Hay varias razones por las que dije que esto es más elegante. Por ejemplo, no implica generar innecesariamente un editor y luego buscar y reemplazar una cadena en el archivo de “tareas pendientes”. Usando git merge --squash también es más fácil de usar en un script. Esencialmente, el razonamiento fue que no necesitas la “interactividad” de git rebase -i en absoluto por esto.

    –Mark Longair

    8 de julio de 2013 a las 15:59


  • Aunque aprecio la ventaja de tener un mensaje de compromiso detallado para grandes cambios como este, también hay una verdadera desventaja de este método sobre el de Chris: hacer un difícil Reiniciar (git reset --hard) toca muchos más archivos. Si está utilizando Unity3D, por ejemplo, apreciará que se toquen menos archivos.

    – Cregox

    26 de noviembre de 2013 a las 12:35

  • Otra ventaja es que git merge --squash es menos probable que produzca conflictos de fusión frente a movimientos/eliminaciones/cambios de nombre en comparación con el cambio de base, especialmente si se está fusionando desde una rama local. (descargo de responsabilidad: basado en una sola experiencia, ¡corríjame si esto no es cierto en el caso general!)

    – Cheezmeister

    27 de febrero de 2014 a las 22:21

  • Siempre soy muy reacio cuando se trata de reinicios completos: usaría una etiqueta temporal en lugar de [email protected]{1} solo para estar seguro, por ejemplo, cuando su flujo de trabajo se interrumpe durante una hora por un corte de energía, etc.

    – Tobías Kienzler

    11 de agosto de 2014 a las 12:18

  • @BT: ¿Destruyó su compromiso? 🙁 No estoy seguro de lo que quiere decir con eso. Podrá volver fácilmente a cualquier cosa que haya confirmado desde el reflog de git. Si tenía trabajo no confirmado, pero los archivos estaban preparados, aún debería poder obtener sus contenidos de vuelta, aunque eso será más trabajo. Sin embargo, si su trabajo ni siquiera fue organizado, me temo que es poco lo que se puede hacer; es por eso que la respuesta dice por adelantado: “Primero verifique que el estado de git esté limpio (desde git reset –hard eliminará los cambios preparados y no preparados)”.

    –Mark Longair

    22 de mayo de 2016 a las 9:55

recomiendo evitar git reset cuando sea posible, especialmente para los principiantes de Git. A menos que realmente necesite automatizar un proceso basado en un número de commits, hay una forma menos exótica…

  1. Coloque las confirmaciones que se van a aplastar en una rama de trabajo (si aún no lo están), use gitk para esto
  2. Echa un vistazo a la rama de destino (por ejemplo, ‘maestro’)
  3. git merge --squash (working branch name)
  4. git commit

El mensaje de confirmación se completará automáticamente en función del squash.

  • Este es el método más seguro: ¡sin reinicio suave / duro (!!), o reflog usado!

    – TeChn4K

    30 de noviembre de 2016 a las 14:08

  • Sería genial si ampliara (1).

    – Adán

    11 de abril de 2017 a las 14:16

  • @Adam: Básicamente, esto significa usar la interfaz GUI de gitk para etiquetar la línea de código que está aplastando y también etiquetar la base sobre la que aplastar. En el caso normal, ambas etiquetas ya existirán, por lo que se puede omitir el paso (1).

    –Brent Bradburn

    11 de abril de 2017 a las 21:48

  • Tenga en cuenta que este método no marca la rama de trabajo como fusionada por completo, por lo que eliminarla requiere una eliminación forzada. 🙁

    – Kyrstellaine

    13 de abril de 2017 a las 20:17

  • Para (1), he encontrado git branch your-feature && git reset --hard HEAD~N la forma más conveniente. Sin embargo, implica reiniciar git nuevamente, lo que esta respuesta intentó evitar.

    – eis

    30 de mayo de 2017 a las 17:01

avatar de usuario
muya_

Gracias a esta útil entrada de blog Descubrí que puedes usar este comando para aplastar las últimas 3 confirmaciones:

git rebase -i HEAD~3

Esto es útil ya que funciona incluso cuando se encuentra en una sucursal local sin información de seguimiento/repositorio remoto.

El comando abrirá el editor de rebase interactivo que luego le permite reordenar, aplastar, reformular, etc. como de costumbre.


Usando el editor de rebase interactivo:

El editor de rebase interactivo muestra las últimas tres confirmaciones. Esta restricción fue determinada por HEAD~3 al ejecutar el comando git rebase -i HEAD~3.

El compromiso más reciente, HEADse muestra primero en la línea 1. Las líneas que comienzan con un # son comentarios/documentación.

La documentación mostrada es bastante clara. En cualquier línea dada, puede cambiar el comando de pick a un comando de su elección.

Prefiero usar el comando fixup ya que esto “aplasta” los cambios de la confirmación en la confirmación de la línea anterior y descarta el mensaje de la confirmación.

Como la confirmación en la línea 1 es HEADen la mayoría de los casos dejarías esto como pick. No se puede utilizar squash o fixup ya que no hay otro compromiso para aplastar el compromiso.

También puede cambiar el orden de las confirmaciones. Esto le permite aplastar o corregir confirmaciones que no son adyacentes cronológicamente.

editor de rebase interactivo


Un ejemplo práctico para el día a día

Recientemente comencé una nueva función. Desde entonces, he cometido dos correcciones de errores. Pero ahora descubrí un error (o tal vez solo un error de ortografía) en la nueva función que comprometí. ¡Que molesto! ¡No quiero que un nuevo compromiso contamine mi historial de compromisos!

Lo primero que hago es corregir el error y hacer un nuevo compromiso con el comentario. squash this into my new feature!.

entonces corro git log o gitk y obtenga el SHA de confirmación de la nueva característica (en este caso 1ff9460).

A continuación, abro el editor de rebase interactivo con git rebase -i 1ff9460~. los ~ después de la confirmación, SHA le dice al editor que incluya esa confirmación en el editor.

A continuación, muevo la confirmación que contiene la corrección (fe7f1e0) debajo de la confirmación de función y cambiar pick a fixup.

Al cerrar el editor, la corrección se integrará en la función de confirmación y mi historial de confirmación se verá limpio y ordenado.

Esto funciona bien cuando todas las confirmaciones son locales, pero si intenta cambiar las confirmaciones que ya se enviaron al control remoto, ¡realmente puede causar problemas a otros desarrolladores que hayan revisado la misma rama!

ingrese la descripción de la imagen aquí

  • Este es el método más seguro: ¡sin reinicio suave / duro (!!) o reflog usado!

    – TeChn4K

    30 de noviembre de 2016 a las 14:08

  • Sería genial si ampliara (1).

    – Adán

    11 de abril de 2017 a las 14:16

  • @Adam: Básicamente, esto significa usar la interfaz GUI de gitk para etiquetar la línea de código que está aplastando y también etiquetar la base sobre la que aplastar. En el caso normal, ambas etiquetas ya existirán, por lo que se puede omitir el paso (1).

    –Brent Bradburn

    11 de abril de 2017 a las 21:48

  • Tenga en cuenta que este método no marca la rama de trabajo como fusionada por completo, por lo que eliminarla requiere forzar la eliminación. 🙁

    – Kyrstellaine

    13 de abril de 2017 a las 20:17

  • Para (1), he encontrado git branch your-feature && git reset --hard HEAD~N la forma más conveniente. Sin embargo, implica reiniciar git nuevamente, lo que esta respuesta intentó evitar.

    – eis

    30 de mayo de 2017 a las 17:01

2020 sencillo solución sin rebase:

git reset --soft HEAD~2 
git commit -m "new commit message"
git push -f

2 significa que las dos últimas confirmaciones se eliminarán. Puedes reemplazarlo por cualquier número.

  • Esta solución no debe ser alentada. Utilizando el-f (force) opción en push es una práctica peligrosa, especialmente si está presionando a un repositorio compartido (es decir, historial público) que hará la vida difícil para los contribuyentes

    – FXQuant Trader

    17 de noviembre de 2020 a las 5:09


  • si el objetivo es agregar este nuevo compromiso para dominar como parte de un pr en curso, podría usar git reset --soft $(git merge-base feature master) y entonces git commit.

    – Karl Pokus

    15 de febrero de 2021 a las 8:42

  • @FXQuantTrader: Si todo el mundo empuja a la fuerza, sucede lo contrario. Casi siempre hay necesidad de empujar con --force. Hacer esto lo alinea bien con el resto del equipo y las diferentes ubicaciones remotas, ya que sabe lo que está sucediendo. También sabes qué parte de la historia ya se ha estabilizado. No hay necesidad de ocultar eso.

    – hakré

    30 de marzo de 2021 a las 23:05


  • Yo diría que empujar con force debería ser en realidad motivado con impactos muy bien comunicados de este enfoque –– Force-pushing va de la mano con rebase y sincronización del trabajo por lo que es mejor, en mi humilde opinión, que más personas conozcan los efectos de esta acción, en lugar de ser un comando exotérico que la gente tiene miedo de usar.

    – Mateo Felipe

    13 abr 2021 a las 23:16

  • De acuerdo con Matheus, forzar el empuje para presentar ramas está bien y debe alentarse con el reajuste. Empujar directamente a principal siempre debe estar restringido de todos modos.

    – Prisa

    18 de diciembre de 2021 a las 21:26


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad