IronWoods.es

Desarrollo web

Blog / Git / Reescribiendo la historia

Cambiar mensajes de commits previamente guardados, puede causar inconsistencias y no se recomienda, pero podría ser necesario y no es siempre peligroso.

Haberlas hailas...

Sin lección de historia, cuando he preguntado a compañeros no sabían cómo hacerlo, es una de esas cosas que parece que nadie ha hecho nunca. Luego lees tutoriales o la documentación de Git, y no parece tan complicado hasta que te cargas el repositorio...

Siempre he acabado desistiendo, ya que las correcciones no eran tan importantes como las posibles complicaciones, sin dejar de preguntarme ¿por qué cambiar un mensaje, no el último, uno anterior, es tan complicado? Supongo que algo que no debes hacer y se hace poco, basta con poder hacerlo, de la forma que sea.

Un día tuve que resolverlo, porque un mensaje del histórico estaba mal como para causar confusión en una revisión posterior y aquí estamos.

Preparación

Primer problema: el editor.

Por defecto la terminal de Git en Windows lanza Vim para hacer los cambios. Yo nunca me he aclarado con él y usar uno externo, como Sublime, no funciona, si cambias un mensaje no se guarda, te quedas a medias sin saber muy bien dónde y a veces, ni siquiera puedes volver al principio...

Otro editor, que también se instala con la terminal de Git y me gusta más es Nano. Hay que cambiar el editor por defecto:

git config --global core.editor nano

Precauciones

Primera regla: no debe haber cambios en el 'stage area'.

Puedes tener problemas al reescribir la historia de mensajes en muchas situaciones, yo voy a indicar cuando lo considero 'bastante' seguro.

1. Necesitas cambiar un mensaje de tu repo local que aún no has enviado al repositorio remoto.

2. Has enviado el commit cuyo mensaje quieres cambiar al repo remoto, pero es un repositorio en el que trabajas sólo tú y del que sólo manejas una copia, es decir que no trabajas sobre el en varios equipos.

Para el resto de situaciones hay un abanico de posibles complicaciones desde las que podemos manejar fácilmente hasta las catastróficas... Toca investigar para ver cuando podemos proceder.

Manos a la obra

La solución pasa por hacer un 'rebase' del repositorio. En humano no informático: abrir la historia para poder ver lo que se quiere cambiar, hacer los cambios, guardar y cerrar.

Un recordatorio: usaré el editor Nano.

Entonces, imaginemos que queremos cambiar el mensaje 3 commits atrás. Podemos abrir el historial de mensajes guardados para poder editarlo de dos formas:

git rebase -i HEAD~3


git rebase -i 634js8

En el primer caso indicamos la posición del mensaje a editar desde nuestra posición anterior y en el segundo el hash (al menos los 6 primeros caracteres) del commit anterior al que queremos editar. Hay una excepción a los dos métodos anteriores: no permiten cambiar el primer commit del histórico, para ello el comando sería:

git rebase -i --root

Este abre el editor con todos los mensajes de commit, incluyendo el primero. Si usamos los métodos previamente mencionados, en las primeras líneas aparece algo como:

File: C:/workspace/tests/.git/rebase-merge/git-rebase-todo


pick 447af68 Este mensaje debería cambiarse.

pick fb78681 Este es el último mensaje guardado.

pick cbc8481 Otro mensaje de commit.


# Rebase 541ed2f..cbc8481 onto 541ed2f (3 commands)

#

Moveremos el cursor con el teclado. Cambiamos "pick" por "reword" en el mensaje/s a editar. Ahora debemos guardar y salir.

Pulsamos Ctrl + O.

Pulsamos Enter para confirmar el nombre del fichero.

Pulsamos Ctrl + X para salir del editor.

Si no hay problemas se abre de nuevo el editor con el mensaje a cambiar. Lo corregimos y se repite el procedimiento.

Pulsamos Ctrl + O.

Pulsamos Enter para confirmar el nombre del fichero.

Pulsamos Ctrl + X para salir del editor.

El rebase debe concluir automáticamente, regresamos al punto de partida con las correcciones realizadas.


Nota: si hemos modificado un mensaje previamente pusheado, forzamos un push para llevar las correcciones al repo remoto.

Entradas relacionadas:

Sitio libre de scripts. Solo efectos HTML / CSS