eliminar deshacer cambios git rebase git-rebase undo

deshacer - git merge



Deshaciendo un git rebase (15)

De hecho, coloco una etiqueta de respaldo en la rama antes de realizar cualquier operación no trivial (la mayoría de las rebases son triviales, pero lo haría si se ve en cualquier lugar complejo).

Entonces, restaurar es tan fácil como git reset --hard BACKUP .

¿Alguien sabe cómo deshacer fácilmente una rebase de git?

La única forma que se me ocurre es ir a ello manualmente:

  • Git Checkout el padre de compromiso a las dos ramas
  • luego crea una rama temporal desde allí
  • cherry-pick todos los commit a mano
  • Reemplazar la rama en la que rebasé por la rama creada manualmente

En mi situación actual, esto va a funcionar porque puedo detectar fácilmente las confirmaciones de ambas ramas (una fue mis cosas, la otra fue la de mis colegas)

Sin embargo, mi enfoque me parece subóptimo y propenso a errores (digamos que acabo de cambiar de base con 2 de mis propias sucursales).

¿Algunas ideas?

Aclaración: estoy hablando de una rebase durante la cual se repitieron un montón de confirmaciones. No solo uno.


Digamos que cambio de maestro a mi rama de función y obtengo 30 nuevos confirmaciones que rompen algo. He encontrado que a menudo es más fácil simplemente eliminar los errores cometidos.

git rebase -i HEAD~31

Rebase interactiva para los últimos 31 confirmaciones (no duele si eliges demasiados).

Simplemente tome las confirmaciones de las que desea deshacerse y márquelas con "d" en lugar de "pick". Ahora, las confirmaciones se eliminan de manera efectiva deshaciendo la rebase (si elimina solo las confirmaciones que acaba de recibir al volver a basar).


En caso de que haya empujado su sucursal al repositorio remoto (generalmente es el origen) y luego haya hecho una rebase exitosa (sin combinación) ( git rebase --abort da "No hay rebase en progreso"), puede restablecer fácilmente la rama usando el comando:

git reset - hard origin / {branchName}

Ejemplo:

$ ~/work/projects/{ProjectName} $ git status On branch {branchName} Your branch is ahead of ''origin/{branchName}'' by 135 commits. (use "git push" to publish your local commits) nothing to commit, working directory clean $ ~/work/projects/{ProjectName} $ git reset --hard origin/{branchName} HEAD is now at 6df5719 "Commit message". $ ~/work/projects/{ProjectName} $ git status On branch {branchName} Your branch is up-to-date with ''origin/{branchName}. nothing to commit, working directory clean


En caso de que no hayas completado el rebase y en medio de él, los siguientes trabajos:

git rebase --abort


En realidad, rebase guarda tu punto de inicio en ORIG_HEAD por lo que generalmente es tan simple como:

git reset --hard ORIG_HEAD

Sin embargo, el reset , la rebase y la merge guardan su puntero HEAD original en ORIG_HEAD , por lo que, si ha ejecutado alguno de esos comandos desde la rebase que está intentando deshacer, entonces tendrá que usar el reflog.


La forma más fácil sería encontrar la confirmación de cabeza de la rama tal como estaba inmediatamente antes de que comenzara la reflog en el reflog ...

git reflog

y restablecer la rama actual a ella (con las advertencias habituales de estar absolutamente seguro antes de restablecer con la opción --hard ).

Supongamos que la confirmación anterior era HEAD@{5} en el registro de referencia:

git reset --hard HEAD@{5}

En Windows, puede que necesite citar la referencia:

git reset --hard "HEAD@{5}"

Puede verificar el historial de la cabeza antigua candidata simplemente haciendo un git log HEAD@{5} ( Windows: git log "HEAD@{5}" ).

Si no ha deshabilitado los reflogs por rama, debería poder simplemente hacer git reflog branchname@{1} ya que una rebase separa el cabezal de la rama antes de volver a unir el cabezal final. Me gustaría volver a comprobar esto, aunque como no he verificado esto recientemente.

Por defecto, todos los reflogs se activan para los repositorios no vacíos:

[core] logAllRefUpdates = true


La respuesta de Charles funciona, pero quizás quieras hacer esto:

git rebase --abort

para limpiar después del reset .

De lo contrario, puede Interactive rebase already started el mensaje " Interactive rebase already started ".


Me sorprende que nadie haya mencionado esto aquí todavía. Rebase deja el estado anterior como ORIG_HEAD , por lo que puede revertir la última rebase ejecutando:

git reset --hard ORIG_HEAD


Para cancelar, puede ingresar el siguiente comando:

git -c core.quotepath=false rebase --abort


Para múltiples confirmaciones, recuerde que cualquier confirmación hace referencia a todo el historial que lleva a esa confirmación. Así que en la respuesta de Charles, lea "el antiguo compromiso" como "el más nuevo de los antiguos compromisos". Si restablece a ese compromiso, volverá a aparecer todo el historial que lleva a ese compromiso. Esto debería hacer lo que quieras.


Restablecer la rama al objeto de compromiso colgante de su antiguo consejo es, por supuesto, la mejor solución, ya que restaura el estado anterior sin gastar ningún esfuerzo. Pero si ha perdido esos compromisos (por ejemplo, porque recogió su repositorio de basura mientras tanto, o este es un clon nuevo), siempre puede volver a introducir la rama nuevamente. La clave para esto es el interruptor --onto .

Digamos que tenías una rama temática llamada imaginativamente topic , que ramificaste del master cuando la punta del master era la confirmación 0deadbeef . En algún momento mientras estaba en la rama del topic , hizo git rebase master . Ahora quieres deshacer esto. Así es cómo:

git rebase --onto 0deadbeef master topic

Esto tomará todas las confirmaciones sobre el topic que no están en el master y las 0deadbeef encima de 0deadbeef .

Con --onto , puedes reorganizar tu historia en casi cualquier forma .

Que te diviertas. :-)


Si desordena algo dentro de un git rebase, por ejemplo, git rebase --abort , si bien tiene archivos no comprometidos, se perderán y git reflog no ayudará. Esto me pasó a mí y tendrás que pensar fuera de la caja aquí. Si tiene suerte como yo y usa IntelliJ Webstorm, puede hacer clic con el botón right-click->local history mouse en- right-click->local history y puede volver al estado anterior de sus archivos / carpetas sin importar los errores que haya cometido con el software de versiones. Siempre es bueno tener otra ejecución a prueba de fallos.


Si rebasó exitosamente contra la rama remota y no puede git rebase --abort , todavía puede hacer algunos trucos para guardar su trabajo y no tener empujes forzados. Supongamos que su sucursal actual que fue rebasada por error se llama your-branch y está rastreando el origin/your-branch

  • git branch -m your-branch-rebased # renombra la rama actual
  • git checkout origin/your-branch # checkout al estado más reciente que se conoce como origen
  • git checkout -b your-branch
  • verifique el git log your-branch-rebased , compárelo con el git log your-branch y defina las confirmaciones que faltan en your-branch
  • git cherry-pick COMMIT_HASH para cada confirmación en your-branch-rebased
  • empuje sus cambios Tenga en cuenta que dos sucursales locales están asociadas con el remote/your-branch y que debe presionar solo your-branch

Siguiendo la solución de @Allan y @Zearin, desearía poder simplemente hacer un comentario, pero no tengo suficiente reputación, así que he usado el siguiente comando:

En lugar de hacer git rebase -i --abort (note el -i ) tuve que hacer simplemente git rebase --abort ( sin el -i ).

Usar tanto -i como --abort al mismo tiempo hace que Git me muestre una lista de uso / opciones.

Por lo tanto, mi estado de rama anterior y actual con esta solución es:

matbhz@myPc /my/project/environment (branch-123|REBASE-i) $ git rebase --abort matbhz@myPc /my/project/environment (branch-123) $


Usar reflog no funcionó para mí.

Lo que funcionó para mí fue similar al descrito here . Abra el archivo en .git / logs / refs que lleva el nombre de la rama que se rebasó y encuentre la línea que contiene "rebase finsihed", algo como:

5fce6b51 88552c8f Kris Leech <[email protected]> 1329744625 +0000 rebase finished: refs/heads/integrate onto 9e460878

Revisa el segundo commit listado en la línea.

git checkout 88552c8f

Una vez confirmado, esto contenía mis cambios perdidos, ramifiqué y dejé escapar un suspiro de alivio.

git log git checkout -b lost_changes