Borrar commits de git: reset, rebase y cherry-pick
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.
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
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
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
Muchas Gracias !! me sirvió perfecto.
saludos!
me has salvado la vida con este blog. gracias amigo