tutorial - resolver conflictos en github




Deshacer una fusión de Git que aún no se ha empujado (18)

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 [email protected]{0}: commit (merge): Merge branch 'master' into my-branch
43b6032 [email protected]{1}: checkout: moving from master to my-branch
e3753a7 [email protected]{2}: rebase finished: returning to refs/heads/master
e3753a7 [email protected]{3}: pull --rebase: checkout e3753a71d92b032034dcb299d2df2edc09b5830e
b41ea52 [email protected]{4}: reset: moving to HEAD^
8400a0f [email protected]{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.


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.


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 .


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.


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.


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 [email protected]{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 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 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".



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





git-merge