rama - Deshacer una fusión de Git que aún no se ha empujado
rama git (26)
Dentro de mi rama maestra, hice un git merge some-other-branch
localmente a git merge some-other-branch
, pero nunca presioné los cambios al maestro de origen. No quise fusionarme, así que me gustaría deshacerlo. Al hacer un git status
después de mi combinación, estaba recibiendo este mensaje:
# On branch master
# Your branch is ahead of ''origin/master'' by 4 commits.
Basado en algunas instrucciones que encontré , traté de correr
git revert HEAD -m 1
pero ahora estoy recibiendo este mensaje con el git status
:
# On branch master
# Your branch is ahead of ''origin/master'' by 5 commits.
No quiero que mi sucursal esté adelante por ningún número de confirmaciones. ¿Cómo vuelvo a ese punto?
En primer lugar, asegúrese de que ha cometido todo.
Luego reinicie su repositorio al estado de trabajo anterior:
$ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36
o utilizando
--hard
(¡ esto eliminará todos los cambios locales, no confirmados! ):$ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 --hard
Utilice el hash que estaba allí antes de que se cometiera una fusión errónea.
Compruebe qué confirmaciones desea volver a confirmar en la parte superior de la versión correcta anterior mediante:
$ git log 4c3e23f529b581c3cbe95350e84e66e3cb05704f commit 4c3e23f529b581c3cbe95350e84e66e3cb05704f ... commit 16b373a96b0a353f7454b141f7aa6f548c979d0a ...
Aplique sus compromisos correctos en la parte superior de la versión correcta de su repositorio de la siguiente manera:
Mediante el uso de cherry-pick (los cambios introducidos por algunas confirmaciones existentes)
git cherry-pick ec59ab844cf504e462f011c8cc7e5667ebb2e9c7
O bien, seleccionando la gama de compromisos por:
Primero verificando los cambios correctos antes de fusionarlos:
git diff 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
Primero verificando los cambios correctos antes de fusionarlos:
git cherry-pick 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
donde este es el rango de las confirmaciones correctas que ha confirmado (excluyendo la combinación erróneamente cometida).
Últimamente, he estado usando git reflog
para ayudar con esto. En su mayoría, esto solo funciona si la combinación SÓLO sucedió, y estaba en su máquina.
git reflog
podría devolver algo como:
fbb0c0f HEAD@{0}: commit (merge): Merge branch ''master'' into my-branch
43b6032 HEAD@{1}: checkout: moving from master to my-branch
e3753a7 HEAD@{2}: rebase finished: returning to refs/heads/master
e3753a7 HEAD@{3}: pull --rebase: checkout e3753a71d92b032034dcb299d2df2edc09b5830e
b41ea52 HEAD@{4}: reset: moving to HEAD^
8400a0f HEAD@{5}: rebase: aborting
La primera línea indica que se produjo una fusión. La segunda línea es el tiempo antes de mi fusión. Simplemente git reset --hard 43b6032
para forzar a esta rama a seguir desde antes de la fusión, y continuar.
Bien, las respuestas que otras personas aquí me dieron fueron cercanas, pero no funcionó. Esto es lo que hice.
Haciendo esto...
git reset --hard HEAD^
git status
... me dio el siguiente estado.
# On branch master
# Your branch and ''origin/master'' have diverged,
# and have 3 and 3 different commit(s) each, respectively.
Luego tuve que escribir el mismo comando git reset
varias veces más. Cada vez que hice eso, el mensaje cambió en uno como se puede ver a continuación.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and ''origin/master'' have diverged,
# and have 3 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and ''origin/master'' have diverged,
# and have 2 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and ''origin/master'' have diverged,
# and have 1 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch is behind ''origin/master'' by 3 commits, and can be fast-forwarded.
En este punto, vi que el mensaje de estado cambió, así que intenté hacer un git pull
, y eso pareció funcionar:
> git pull
Updating 2df6af4..12bbd2f
Fast forward
app/views/truncated | 9 ++++++---
app/views/truncated | 13 +++++++++++++
app/views/truncated | 2 +-
3 files changed, 20 insertions(+), 4 deletions(-)
> git status
# On branch master
En pocas palabras, mis órdenes se reducen a esto:
git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git pull
Con git reflog
compruebe qué compromiso es uno antes de la fusión (git reflog será una mejor opción que git log). Luego puedes restablecerlo usando:
git reset --hard commit_sha
También hay otra manera
git reset --hard HEAD~1
te devolverá 1 cometer.
Tenga en cuenta que los archivos modificados y no confirmados / no ocultos se restablecerán a su estado no modificado . Para mantenerlos alejados de los cambios o ver la opción de --merge
continuación.
Como @Velmont sugirió a continuación en su respuesta, en este caso directo usando:
git reset --hard ORIG_HEAD
podría dar mejores resultados, ya que debería preservar sus cambios. ORIG_HEAD
apuntará a una confirmación directamente antes de que se haya producido la fusión, por lo que no tiene que buscarla usted mismo.
Otro consejo es usar el interruptor --hard
lugar de --hard
ya que no restablece archivos innecesariamente:
--unir
Restablece el índice y actualiza los archivos en el árbol de trabajo que son diferentes entre <commit> y HEAD, pero mantiene aquellos que son diferentes entre el índice y el árbol de trabajo (es decir, los que tienen cambios que no se han agregado).
Con el Git moderno, puedes:
git merge --abort
Sintaxis más antigua:
git reset --merge
Vieja escuela:
git reset --hard
Pero en realidad, vale la pena notar que git merge --abort
solo es equivalente a git reset --merge
dado que MERGE_HEAD
está presente. Esto se puede leer en la ayuda de Git para el comando de combinación.
git merge --abort is equivalent to git reset --merge when MERGE_HEAD is present.
Después de una fusión fallida, cuando no hay MERGE_HEAD
, la fusión fallida se puede deshacer con git reset --merge
, pero no necesariamente con git merge --abort
, por lo que no solo son sintaxis antigua y nueva para la misma cosa .
Personalmente, encuentro que git reset --merge
mucho más potente y útil en el trabajo diario, así que esa es la que siempre uso.
Con las nuevas versiones de Git, si aún no ha confirmado la fusión y tiene un conflicto de fusión , simplemente puede hacer:
git merge --abort
De man git merge
:
[Esto] solo se puede ejecutar después de que la fusión haya generado conflictos.
git merge --abort
el proceso de fusión e intentará reconstruir el estado previo a la fusión.
Creo que puedes hacer git rebase -i [hash] [branch_name]
donde [hash]
es el hash de identificación para lo que sea que quieras retroceder más uno (o las devoluciones que quieras) y luego eliminar las líneas para La confirmación en el editor de que ya no quieres más. Guarda el archivo. Salida. Orar. Y debe ser rebobinado. Puede que tengas que hacer un git reset --hard
, pero debería estar bien en este punto. También puede usar esto para sacar confirmaciones específicas de una pila, si no quiere mantenerlas en su historial, pero eso puede dejar su repositorio en un estado que probablemente no desee.
Debe restablecer a la confirmación anterior. Esto debería funcionar:
git reset --hard HEAD^
O incluso HEAD^^
para revertir que revertir cometer. Siempre puede dar una referencia completa de SHA si no está seguro de cuántos pasos atrás debe dar.
En caso de que tenga problemas y su rama maestra no haya tenido cambios locales, puede restablecer a origin/master
.
En este caso, deseará restablecer su rama con git reset --hard <branch_name>
. Si desea guardar sus cambios antes de restablecerlos, asegúrese de crear una nueva sucursal y git checkout <branch_name>
.
Puede restablecer el estado a un compromiso específico con git reset --hard <commit_id>
también.
Si se han git revert <branch_name>
los cambios, puede usar git revert <branch_name>
lugar. Asegúrese de revisar cómo usar git revert y git checkout en otros escenarios también.
Es extraño que faltara el comando más simple. La mayoría de las respuestas funcionan, pero deshacer la fusión que acabas de hacer, esta es la forma fácil y segura :
git reset --merge ORIG_HEAD
La referencia ORIG_HEAD
apuntará a la confirmación original desde antes de la fusión.
(La opción --merge
no tiene nada que ver con la fusión. Es como git reset --hard ORIG_HEAD
, pero más segura ya que no toca los cambios no confirmados).
La más simple de las posibilidades más simples, mucho más simple que lo que se dice aquí:
Retire su sucursal local (local, no remota) y tire de nuevo. De esta manera, deshará los cambios en su rama maestra y cualquier persona se verá afectada por el cambio que no desea impulsar. Comience de nuevo.
La respuesta más simple es la dada por odinho - Velmont
Primero, git reset --merge ORIG_HEAD
Para aquellos que buscan restablecer después de que se empujan los cambios, haga esto (porque esta es la primera publicación que se ve para cualquier pregunta de combinación de restablecimiento de git)
git push origin HEAD --force
Esto se restablecerá de manera que no volverá a obtener los cambios combinados después de la extracción.
Llegó a esta pregunta que también busca volver a coincidir con el origen (es decir, NO se envía antes del origen). Investigando más a fondo, encontramos que hay un comando de reset
para exactamente eso:
git reset --hard @{u}
Nota: @{u}
es una abreviatura de origin/master
. (Y, por supuesto, necesita ese repositorio remoto para que esto funcione).
Pude resolver este problema con un solo comando que no implica buscar un ID de confirmación.
git reset --hard remotes/origin/HEAD
La respuesta aceptada no funcionó para mí, pero este comando logró los resultados que estaba buscando.
Puede usar solo dos comandos para revertir una combinación o reinicio mediante una confirmación específica:
-
git reset --hard commitHash
(debe usar el commit que desea reiniciar, por ejemplo, 44a587491e32eafa1638aca7738) -
git push origin HEAD --force
(Enviar la nueva rama maestra local a origen / maestro)
Buena suerte y adelante!
Puedes usar git reflog
para encontrar el checkout anterior. A veces es un buen estado al que deseas volver.
Concretamente,
$ git reflog
$ git reset --hard HEAD@{0}
Puedes usar el comando git-reset.
git-reset - Restablece la CABEZA actual al
Estado especificado. git reset [--mixed |
--soft | --duro | --merge] [-q] [] git reset [-q] []
[-]… reinicio de git - parche
[] [-] […]
Si aún no lo has cometido, solo puedes usar
$ git checkout -f
Se deshará la fusión (y todo lo que hiciste).
Si desea una solución de línea de comandos, sugiero que simplemente vaya con la respuesta de MBO.
Si eres un novato, puede que te guste el enfoque gráfico:
- Kick off
gitk
(desde la línea de comandos, o haga clic derecho en el buscador de archivos si tiene eso) - Puede detectar fácilmente el compromiso de fusión allí: el primer nodo desde la parte superior con dos padres
- Siga el enlace al primer / padre izquierdo (el de su rama actual antes de la fusión, generalmente rojo para mí)
- En la confirmación seleccionada, haga clic con el botón derecho en "Restablecer rama aquí", seleccione el restablecimiento completo allí
Si has cometido la fusión:
git reset HEAD~1
# Make sure what you are reverting is in fact the merge files
git add .
git reset --hard
Si observa que necesita revertir inmediatamente después de la fusión y no ha hecho nada más después del intento de fusión, puede git reset --hard HEAD@{1}
este comando: git reset --hard HEAD@{1}
.
Esencialmente, su combinación sha
estará apuntando a HEAD@{0}
si no se ha confirmado nada más después de la combinación y, por lo tanto, HEAD@{1}
será el punto anterior antes de la combinación.
Si su combinación y las confirmaciones correspondientes aún no se enviaron, siempre puede cambiar a otra rama, eliminar la original y volver a crearla.
Por ejemplo, accidentalmente fusioné una rama de desarrollo en maestro y quise deshacer eso. Usando los siguientes pasos:
git checkout develop
git branch -D master
git branch -t master origin/master
Voila! El maestro se encuentra en la misma etapa que el origen, y se borra su estado mal fusionado.
Solo para ver una opción adicional, he estado siguiendo en su mayoría el modelo de bifurcación que se describe aquí: http://nvie.com/posts/a-successful-git-branching-model/ y, como tal, se ha estado fusionando con --no-ff
(sin avance rápido) por lo general.
Acabo de leer esta página, ya que accidentalmente fusioné una rama de prueba en lugar de mi rama de lanzamiento con el maestro para el despliegue (sitio web, el maestro es lo que está activo). La rama de prueba tiene otras dos ramas fusionadas y un total de alrededor de seis confirmaciones.
Así que para revertir todo el compromiso solo necesitaba un git reset --hard HEAD^
y revertió toda la fusión. Como las fusiones no se enviaron rápidamente, la fusión fue un bloque y un paso atrás es "rama no fusionada".
Suponiendo que su maestro local no estuviera delante del origen / maestro, debería poder hacerlo
git reset --hard origin/master
Entonces, su rama master
local debe tener un aspecto idéntico al origin/master
.
Ver el capítulo 4 en el libro Git y la publicación original de Linus Torvalds .
Para deshacer una fusión que ya fue empujada :
git revert -m 1 commit_hash
Asegúrese de revertir la reversión si está comprometiendo la rama nuevamente, como dijo Linus.
Estrategia: Crear una nueva rama desde donde todo estaba bien.
Fundamento: Revertir una fusión es difícil. Hay demasiadas soluciones, dependiendo de muchos factores, como si ha comprometido o impulsado su fusión o si hubo nuevos compromisos desde su fusión. También es necesario tener un conocimiento relativamente profundo de git para adaptar estas soluciones a su caso. Si sigue ciegamente algunas instrucciones, puede terminar con una "fusión vacía" en la que no se fusionará nada, y los intentos de fusión posteriores harán que Git le diga "Ya está actualizado".
Solución:
Digamos que quieres fusionar dev
en feature-1
.
Busque la revisión que desea recibir de la combinación:
git log --oneline feature-1 a1b2c3d4 Merge branch ''dev'' into ''feature-1'' <-- the merge you want to undo e5f6g7h8 Fix NPE in the Zero Point Module <-- the one before the merge, you probably want this one
Échale un vistazo (retrocede en el tiempo):
git checkout e5f6g7h8
Crea una nueva rama desde allí y échale un vistazo:
git checkout -b feature-1
Ahora puedes reiniciar tu fusión:
Fusionar:
git merge dev
Arregla tus conflictos de fusión.
Commit:
git commit
Cuando esté satisfecho con los resultados, elimine la rama anterior:
git branch --delete feature-1