¿Alguien sabe cómo deshacer fácilmente un rebase de git?
La única forma que se me ocurre es hacerlo manualmente:
En mi situación actual esto va a funcionar porque puedo detectar fácilmente los commits de ambas ramas (una era cosa mía, la otra era cosa de mi colega).
Sin embargo, mi enfoque me parece subóptimo y propenso a errores (digamos que acabo de rebasar con 2 de mis propias ramas).
¿Alguna idea?
Aclaración: Estoy hablando de un rebase durante el cual se reprodujeron un montón de commits. No sólo uno.
La forma más fácil sería encontrar el commit principal de la rama tal y como estaba inmediatamente antes de que empezara el rebase en el reflog...
git reflog
y reajustar la rama actual a ella (con las advertencias habituales sobre estar absolutamente seguro antes de reajustar con la opción --hard
).
Supongamos que la antigua confirmación era HEAD@{5}
en el registro de referencia:
git reset --hard HEAD@{5}
En Windows, es posible que tenga que citar la referencia:
git reset --hard "HEAD@{5}"
Puedes comprobar el historial del candidato a cabeza antigua simplemente haciendo un git log HEAD@{5}
(Windows: git log "HEAD@{5}"
).
Si no has desactivado los reflogs por rama, deberías poder hacer simplemente git reflog branchname@{1}
ya que un rebase separa la cabeza de la rama antes de volver a unirla a la cabeza final. Yo volvería a comprobar esto, sin embargo, ya que no he verificado esto recientemente.
Por defecto, todos los reflogs están activados para los repositorios no desnudos:
[core]
logAllRefUpdates = true
Restablecer la rama al objeto de confirmación colgante de su antigua punta es, por supuesto, la mejor solución, porque restaura el estado anterior sin gastar ningún esfuerzo. Pero si resulta que ha perdido esos commits (por ejemplo, porque ha recogido su repositorio en el ínterin, o es un clon fresco), siempre puede volver a basar la rama de nuevo. La clave para esto es el interruptor --onto
.
Digamos que tiene una rama de tema llamada imaginativamente "tema", que se ramificó desde "maestro" cuando la punta de "maestro" era el commit "0deadbeef". En algún momento, mientras que en la rama topic
, hiciste git rebase master
. Ahora quieres deshacer esto. He aquí cómo:
git rebase --onto 0deadbeef master topic
Esto tomará todos los commits en topic
que no estén en master
y los reproducirá encima de 0deadbeef
.
Con --onto
, puedes reorganizar tu historia en casi cualquier forma.
Diviértete. :-)
En el caso de los commits múltiples, recuerda que cualquier commit hace referencia a toda la historia que lleva a ese commit. Así que en la respuesta de Charles, lee "el commit antiguo" como "el más reciente de los commits antiguos". Si restableces ese commit, entonces todo el historial que lleva a ese commit volverá a aparecer. Esto debería hacer lo que quieres.