Borrar commits de git: reset, rebase y cherry-pick

junio 12, 2015

Aunque no está bien visto ya que estamos «borrando la historia» 🙂 , puede ocurrir que queramos borrar varios commits que hemos hecho en algún momento y hemos subido al repositorio.

Si se trata de borrar el último commit que hemos hecho, es tan fácil como ejecutar el siguiente comando:

git reset HEAD

El comando anterior eliminará el último commit del repositorio.

El problema viene cuando queremos borrar más de un commit (y no justamente el último). En estos casos tenemos dos opciones, utilizar «rebase» para borrar uno o más commit consecutivos o utilizar «cherry-pick«, que nos permitirá borrar commits no consecutivos.

Para los ejemplos, vamos a utilizar el siguiente árbol de commits:

Número Hash Mensaje
1 8c2aafb Bug de javascript
2 be54fcb Cambios en la interfaz
3 22bb985 Actualizar base de datos
4 6c3813c Bug en la creación de pedidos
5 a3d37d5 Añadir bundle de usuarios
6 741aabb Incluir librería PDF
7 a479739 Añadir proyecto a git


Utilizando rebase

Siguiendo como referencia el «git log» anterior, queremos borrar los commits 2 y 3 (be54fcb y 22bb985). Como son consecutivos, podemos utilizar «rebase».

La utilización genérica de «rebase» sería la siguiente:

git rebase --onto <nombre de la branch>~<numero del primer commit a borrar> <nombre de la branch>~<primer commit que queremos mantener> <nombre de la branch>

En el ejemplo en el que queremos borrar los commits 2 y 3:

git rebase --onto master~3 master~1 master

Como vemos, indicamos el primer commit desde el cual queremos borrar (el número 3) e indicamos hasta el primer commit que queremos mantener (el número 1), por lo que se borrarán los commits 3 y 2.


Utilizando Cherry Pick

En este ejemplo, queremos borrar commits no consecutivos de nuestro repositorio. En este caso queremos borrar los commits número 2 y 4. Para este caso no nos queda más remedio que utilizar el comando «cherry-pick«.

Vamos primero con los pasos genéricos que deberemos seguir:

  • Paso 1: Encontrar el commit justo anterior al commit que queremos borrar.
  • Paso 2: Hacemos un «checkout» de ese commit con el comando:
    git checkout <commit hash>
  • Paso 3: Creamos una nueva rama utilizando nuestra posición actual:
    git checkout -b <nueva branch>
  • Paso 4: Ahora tenemos que añadir el commit siguiente al commit que queremos borrado, para ello utilizamos el comando «cherry-pick»:
    git cherry-pick <commit hash>
  • Paso 5: Repetimos el paso 4 para todos los commits que queremos mantener.
  • Paso 6: Volvemos a la branch original que queríamos arreglar:
    git checkout <branch original>
  • Paso 7: Ahora hacemos un «hard reset» sobre la branch original al commit anterior al que queríamos borrar:
    git reset --hard <commit hash>
  • Paso 8: Hacemos un merge con la branch que hemos creado para borrar los commits:
    git merge <nueva branch>
  • Paso 9: Hacemos un push al repositorio.
    git push --force origin <branch original>


Los veremos mucho más claro con un ejemplo. Con los siguientes comandos borraremos los commits 2 y 4 de nuestro repositorio:

# Checkout al commit justo anterior al que queremos borrar (en este ejemplo, al 5).
git checkout a3d37d5
# Creamos una nueva rama.
git checkout -b reparar
# Añadimos el commit contiguo al commit que queremos borrar (en este ejemplo, el 3).
git cherry-pick 22bb985
# Añadimos el commit contiguo al commit que queremos borrar (en este ejemplo, el 1).
git cherry-pick 8c2aafb
# Checkout master.
git checkout master
# Reset en la branch master al commit justo anterior al que queríamos borrar (en este ejemplo, al 5).
git reset --hard a3d37d5
# Hacemos merge de nuestra rama con la master.
git merge reparar
# Hacemos push de la rama master.
git push --hard origin master

Como nota final recordar que los comandos rebase y cherry-pick son muy peligrosos. Solo deberíamos utilizarlos como última opción. Cuidado si borramos commits en ramas que están siendo utilizadas por otros usuarios.

Tags ; , , , ,

5 comentarios

    Leandro Ago 27, 2016

    Muy útil. Pero podrías, por favor, explicarme cómo hacer para eliminar cuando hay un sólo commit en todo el proyecto. Ya que haga lo que haga no logro conseguir borrar la referencia de HEAD a ese commit. Básicamente quiero eliminar todos los commits del proyecto… Conocés la manera de hacerlo? Gracias

    Responder
      Fernando Mar 22, 2017

      No es posible… git siempre debe tener al menos un commit al cual apuntar, es decir si no tiene commits es como si «eliminaras» el proyecto git

      Responder
    ivan antonio butron sossa Jul 17, 2018

    hola interesante aporte, sera que alguien me ayuda en otro problema parecido?
    yo quiero hacer un rebase de mi branch con mi master remoto pero solo con mi ultimo commit de mi branch. queria hacer skip rebase hasta llegar al ultimo commit pero no saca mis ultimas cosas agregadas.
    si alguien me ayuda, mil gracias por adelantado

    Responder
    Boris Jul 08, 2019

    Muchas Gracias !! me sirvió perfecto.

    saludos!

    Responder
    Sebastian Sep 20, 2019

    me has salvado la vida con este blog. gracias amigo

    Responder

Responde a Sebastian Cancelar la respuesta

Los comentarios son moderados y se utiliza rel="nofollow" para los enlaces.