tutorial rama qué problemas crear conflictos conflicto con git undo git-merge

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?


  1. En primer lugar, asegúrese de que ha cometido todo.

  2. Luego reinicie su repositorio al estado de trabajo anterior:

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36

    o utilizando --hardesto 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.

  3. 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 ...

  4. 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:

  1. git reset --hard commitHash (debe usar el commit que desea reiniciar, por ejemplo, 44a587491e32eafa1638aca7738)
  2. 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

[] [-] […]

GIT-Reset


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:

  1. Kick off gitk (desde la línea de comandos, o haga clic derecho en el buscador de archivos si tiene eso)
  2. Puede detectar fácilmente el compromiso de fusión allí: el primer nodo desde la parte superior con dos padres
  3. Siga el enlace al primer / padre izquierdo (el de su rama actual antes de la fusión, generalmente rojo para mí)
  4. 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 .



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 .

  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

  2. Échale un vistazo (retrocede en el tiempo):

    git checkout e5f6g7h8

  3. Crea una nueva rama desde allí y échale un vistazo:

    git checkout -b feature-1

Ahora puedes reiniciar tu fusión:

  1. Fusionar: git merge dev

  2. Arregla tus conflictos de fusión.

  3. Commit: git commit

  4. Cuando esté satisfecho con los resultados, elimine la rama anterior: git branch --delete feature-1