El rebase interactivo es a veces llamado la «navaja suiza» de Git – ¡porque contiene tantas herramientas diferentes, para tantos casos de uso diferentes! Sin embargo, hay un caso de uso principal y general: la limpieza de tu historial de commit local.

Ten en cuenta la palabra «local»: sólo debería usarse para limpiar tu propio historial de commit local, por ejemplo antes de integrar una de tus ramas de características en una rama del equipo. Por el contrario, NO debe utilizarse en el historial de confirmaciones que ya ha sido empujado y compartido en un repositorio remoto. El rebase interactivo es una de esas herramientas que «reescriben» el historial de Git – y no deberías hacerlo en commits que ya han sido compartidos con otros.

Con este pequeño mensaje de advertencia fuera del camino, ¡vamos a ver algunos ejemplos prácticos!

Nota: para facilitar la visualización de los escenarios y flujos de trabajo en este post, he estado utilizando la GUI de escritorio de Git «Tower» en algunas de mis capturas de pantalla.

Corrección de un mensaje de commit antiguo

A veces te das cuenta de un error tipográfico en un mensaje de commit antiguo – o te has olvidado de mencionar algo en la descripción que es digno de mención. Si estuviéramos hablando de la última confirmación, podríamos haber utilizado simplemente la opción --amend del comando git commit. Pero para los commits más antiguos tendrá que utilizar el rebase interactivo para cambiarlos después del hecho.

Aquí hay un ejemplo de un mensaje de commit que ha salido terriblemente mal y que queremos corregir:

Un mensaje de commit malo que necesita correcciónUn mensaje de commit malo que necesita corrección

El primer paso en cualquier sesión de rebase interactivo es determinar qué parte del historial de commits quiere manipular. Tomando de nuevo el ejemplo anterior: para cambiar este commit malo tenemos que iniciar la sesión en su commit padre.

Iniciando nuestra sesión de rebase interactivoIniciando nuestra sesión de rebase interactivo

Ahora podemos alimentar el hash de este commit inicial al comando de rebase interactivo:

$ git rebase -i 0023cddd

Se abrirá ahora una ventana del editor, que contiene una lista de los commits que acaba de seleccionar para su manipulación. Y no te sorprendas porque están en orden inverso: en una sesión de rebase interactivo, Git volverá a aplicar los commits antiguos, ítem tras ítem – lo que significa que invertir el orden es correcto desde la perspectiva de Git.

Ventana del editor con los commits seleccionadosVentana del editor con los commits seleccionados

Otra cosa importante a tener en cuenta sobre esta ventana del editor: ¡no realizas las manipulaciones reales aquí! O, en este ejemplo concreto, NO se va a cambiar el mensaje de confirmación aquí. En su lugar, sólo marca la confirmación que desea cambiar con una palabra clave de acción. En nuestro caso, como queremos cambiar el mensaje de un commit, marcamos la línea con «reword». Si luego guardas y cierras esta ventana del editor, se abrirá una nueva que contendrá el mensaje de la confirmación anterior. Ahora es el momento de hacer finalmente los cambios:

Por fin, podemos hacer nuestros cambiosPor fin, podemos hacer nuestros cambios

Después de guardar y cerrar una vez más, la sesión de rebase interactivo se ha completado y nuestro antiguo mensaje de confirmación ha sido corregido!

Combinar múltiples confirmaciones en una

Otro caso de uso para el rebase interactivo es cuando se quiere combinar múltiples comentarios antiguos en uno solo. Aunque, por supuesto, se aplica la regla de oro del control de versiones: en la mayoría de las situaciones, es beneficioso crear más commits y más pequeños en lugar de unos pocos grandes. Sin embargo, como en todo, podemos encontrarnos con que nos hemos pasado y ahora queremos fusionar dos o más commits antiguos en uno solo.

Para hacer un ejemplo concreto, digamos que queremos combinar los siguientes commits seleccionados en uno solo:

Combinemos múltiples commits en unoCombinemos múltiples commits en uno

Al igual que en nuestro primer caso, comenzamos iniciando la sesión de rebase interactivo al menos en el commit padre del que queremos manipular.

$ git rebase -i 2b504bee

De nuevo, se abrirá una ventana del editor, listando la parte de nuestro historial de commits que queremos manipular:

Marcando líneas con "squash"Marcando líneas con «squash»

La palabra clave de acción que vamos a utilizar aquí se llama «squash». Y sólo hay un dato importante que debes saber sobre el squash para poder utilizarlo: la línea que marquemos con la palabra clave «squash» se combinará con la línea directamente superior. Por eso, como puedes ver en mi captura de pantalla de arriba, he marcado la línea #2 con «squash» para combinarla con la línea #1.

Ahora podemos guardar y cerrar la ventana del editor y de nuevo observar y aparecer una nueva ventana: ahora se nos pide que proporcionemos un mensaje de commit para el nuevo commit que se crea al combinar esos dos antiguos.

Escribiendo un nuevo mensaje para el nuevo commit aplastadoEscribiendo un nuevo mensaje para el nuevo commit aplastado

Después de guardar y cerrar esta ventana del editor, verás que se ha creado un nuevo commit que contiene los changesets de ambos commits antiguos. Voilá!

Corregir un error

Otro caso de uso del rebase interactivo es cuando encuentras un error en uno de tus commits anteriores. Y no importa en qué te equivocaste exactamente: podrías haber olvidado añadir un determinado cambio, deberías haber borrado un archivo, o simplemente haber introducido una errata…

La tendencia natural, en tal situación, es simplemente crear un nuevo commit que corrija el error. Pero por otro lado, esto desordenará nuestro historial de commits: hacer un commit original, y luego añadir un commit «curita» sólo para arreglar algunos errores… esa es una forma desordenada de trabajar. Su historial de commits pronto será difícil de entender, porque está lleno de todos esos pequeños «commits de corrección rápida».

Aquí es donde «fixup», una de las herramientas que vienen con interactive rebase, es muy útil. Fixup toma este commit de «arreglo rápido», aplica sus cambios al commit original (corrigiéndolo), y luego se deshace del commit curita:

Cómo funciona "fixup"Cómo funciona «fixup»

¡Después de que hayamos terminado, parece como si nunca hubiera habido un problema con nuestro commit original! Así que vamos a recorrer esto usando un ejemplo práctico.

El primer paso es hacer lo que sea necesario para arreglar el problema: esto podría significar añadir un nuevo archivo, hacer cambios en los existentes, eliminar archivos obsoletos… «sólo» hay que producir los cambios que corrigen el error.

El siguiente paso es confirmar estos cambios en el repositorio – pero con un pequeño extra: al hacer el commit, vamos a utilizar la bandera --fixup y le diremos a Git el hash de nuestro commit malo:

$ git add corrections.txt$ git commit --fixup 2b504bee

Cuando ahora eches un vistazo al historial de commit, verás que se ha creado un commit de aspecto bastante ordinario – probablemente no la magia y los fuegos artificiales que hubieras esperado. Pero si echas un vistazo más de cerca, verás que algo está sucediendo: el nuevo commit ha sido automáticamente precedido por «fixup !» y el commit subject de nuestro commit malo.

El commit original y el commit corregidoEl commit original y el commit corregido

El tercer paso ahora es iniciar la sesión de rebase interactivo. De nuevo, elegimos el padre de nuestro commit malo como punto de partida…

$ git rebase -i 0023cddd --autosquash

… y como segunda parte de la salsa secreta, estamos usando la bandera --autosquash. Esta opción hace que no tengamos que hacer nada en la ventana del editor que ahora está abierta. Fíjate bien en la situación:

Nuestro commit arreglado está marcado como "fixup" y ordenado en la posición correctaNuestro commit arreglado está marcado como «fixup» y ordenado en la posición correcta

Verás que Git hizo automáticamente dos cosas por nosotros:

  1. Marcó nuestro commit arreglado como «fixup.»
  2. Reordenó las líneas para que nuestro commit band-aid aparezca directamente debajo de nuestro commit malo. Esto se debe a que el fixup funciona exactamente igual que el squash, ya que se combina con la línea anterior.

En otras palabras: no hay nada más que hacer que guardar y cerrar la ventana del editor.

Volvamos a echar un vistazo al historial de commits:

¡Un final feliz!Un final feliz!

No sólo nuestro commit originalmente malo contiene ahora los cambios de nuestro commit band-aid. Pero además, ¡el feo commit de la tirita ha desaparecido del historial de commits! Todo es bonito y limpio, como si nunca hubiera habido un problema!

Descubra el poder del rebase interactivo

Hay muchos casos de uso para el rebase interactivo – y la mayoría de ellos en el departamento de «corrección de errores». Para una visión general de otras cosas útiles que puedes hacer, te recomiendo el «Kit de primeros auxilios para Git» gratuito: es una colección de vídeos cortos (2-3 minutos por episodio) que te ayudan a aprender a deshacer errores usando el rebase interactivo y otras herramientas de Git.

Nota del editor: ¡Tuve que usar el rebase interactivo al revisar este mismo post! Uno de mis commits incluía una imagen de más de 1MB, lo que va en contra de las reglas del proyecto de la web de GitLab. Tuve que volver atrás y arreglar ese commit para incluir una imagen de tamaño correcto en su lugar. ¡Gracias por la lección, universo! 😁

Más consejos y trucos de Git

  • 15 consejos de Git para mejorar tu flujo de trabajo
  • Cómo el clon parcial de Git te permite obtener sólo el archivo grande que necesitas
  • ¡Git sucede! 6 errores comunes de Git y cómo solucionarlos

Acerca del autor invitado

Tobias Günther es el CEO de Tower, el popular cliente de escritorio de Git que ayuda a más de 100.000 desarrolladores de todo el mundo a ser más productivos con Git.

Imagen de portada por David Taljat en Pexels

Deja una respuesta

Tu dirección de correo electrónico no será publicada.