error de git stash: git stash pop y terminó con conflictos de fusión

200

Hice un git stash popy terminé con conflictos de fusión. Eliminé los archivos del sistema de archivos e hice lo git checkoutque se muestra a continuación, pero cree que los archivos aún no están fusionados. Luego intenté reemplazar los archivos y hacer un resultado git checkoutnuevo y el mismo. Intenté forzarlo con la -fbandera. ¡Cualquier ayuda sería apreciada!

chirag-patels-macbook-pro:haloror patelc75$ git status
app/views/layouts/_choose_patient.html.erb: needs merge
app/views/layouts/_links.html.erb: needs merge
# On branch prod-temp
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   db/schema.rb
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       unmerged:   app/views/layouts/_choose_patient.html.erb
#       unmerged:   app/views/layouts/_links.html.erb

chirag-patels-macbook-pro:haloror patelc75$ git checkout app/views/layouts/_choose_patient.html.erb
error: path 'app/views/layouts/_choose_patient.html.erb' is unmerged
chirag-patels-macbook-pro:haloror patelc75$ git checkout -f app/views/layouts/_choose_patient.html.erb
warning: path 'app/views/layouts/_choose_patient.html.erb' is unmerged
Chirag Patel
fuente
Nota: restaurar el estado antes de que el git stash apply/popdebería ser más fácil con Git 2,5 (Q2 2015), ya que el árbol de trabajo ahora debe estar limpia: véase mi respuesta a continuación
VonC

Respuestas:

219

Ver man git merge ( CÓMO RESOLVER CONFLICTOS ):

Después de ver un conflicto, puede hacer dos cosas:

  • Decide no fusionar. Las únicas limpiezas que necesita son restablecer el archivo de índice a la confirmación HEAD para revertir 2. y limpiar los cambios del árbol de trabajo realizados por 2. y 3 .; git-reset --hard se puede usar para esto.

  • Resolver los conflictos. Git marcará los conflictos en el árbol de trabajo. Edite los archivos en forma y git agréguelos al índice. Usa git commit para sellar el trato.

Y bajo VERDADERO FUSIÓN (para ver a qué se refiere 2. y 3.):

Cuando no es obvio cómo conciliar los cambios, sucede lo siguiente:

  1. El puntero HEAD permanece igual.

  2. La referencia MERGE_HEAD está configurada para apuntar a la otra cabeza de rama.

  3. Las rutas que se fusionaron limpiamente se actualizan tanto en el archivo de índice como en su árbol de trabajo.

  4. ...

Por lo tanto: utilícelo git reset --hardsi desea eliminar los cambios de alijo de su árbol de trabajo, o git resetsi solo desea limpiar el índice y dejar que los conflictos en su árbol de trabajo se fusionen a mano.

En man git stash ( OPTIONS, pop ) puedes leer además:

Aplicar el estado puede fallar con los conflictos; en este caso, no se elimina de la lista oculta. Debe resolver los conflictos a mano y llamar a git stash drop manualmente después.

tanascio
fuente
9
De hecho, incluso después de soltar un alijo, aún es posible (aunque más difícil) recuperarlo nuevamente, porque el conjunto de cambios todavía existe en el repositorio. stackoverflow.com/search?q=git+recover+dropped+stash
phils
3
@nalply: ¿eso es bueno o malo? Usted es bienvenido para mejorar mi respuesta, en la que no se entiende, en primer lugar ...
tanascius
1
Creo que la revisión del código fuente es un dominio complejo de problemas. Es fácil confundirse. Sigo pensando que su respuesta es buena porque reconfirmó mi enfoque.
finalmente
1
No solo me ayudó mucho darme cuenta de que el alijo no se ha eliminado como supuse que sí, sino que esto explica por qué mi alijo siguió creciendo incluso cuando estaba seguro de que no me había olvidado de recuperar cosas de él.
Thor84no
11
"La aplicación del estado puede fallar con los conflictos; en este caso, no se elimina de la lista oculta". Esta es la parte más importante de la publicación, en mi opinión. Considere la posibilidad de editar su respuesta para ponerla al frente junto con las palabras NO PÁNICO en letras grandes y amigables. (+1 ya sin embargo.) Gracias.
Patrick M
42

Me sucedió algo similar. Todavía no quería organizar los archivos, así que los agregué git addy luego lo hice git reset. Básicamente, esto solo agregó y luego eliminó mis cambios pero eliminó los caminos no fusionados.

Aaron
fuente
44
Esto parece ser mejor que usarlo reset --hardporque no sobrescribe sus archivos (excepto los que tienen problemas de fusión). ¡Gracias!
sinelaw
Todavía no quería organizar los archivos, así que los agregué , ¿no addmuestra el contenido del árbol de trabajo al índice? No creo entender por qué su respuesta funciona a partir de la descripción.
Drew Noakes
2
git addlos presenta pero git reset, lo que hago inmediatamente después, los desestabiliza. Esencialmente, despeja los caminos no fusionados y me devuelve a mi árbol de trabajo normal fingiendo git.
Aaron
3
No es necesario git addsi vas a hacerlo git reset. El git resetefectivamente "deshace" el git add. git reset( --mixed<- predeterminado) efectivamente no toca el directorio de trabajo, por lo que exactamente lo que estaba en su directorio de trabajo, fusionar conflictos y todo, se deja solo. Sin embargo, el índice (y técnicamente el encabezado de la rama) se restablece (sin una referencia a la que se restablecen HEAD, lo que probablemente significa que no hay cambios para el encabezado de la rama, y ​​deshace efectivamente cualquier git addhecho en el índice, así como también borra el estado de las rutas no fusionadas) .
bambams
3
La secuencia , editar / resolver , git resety git stash dropfunciona bien. Hace lo git stash popque hubiera hecho sin conflictos. Parece que no git addes necesario; aunque puede ser útil, tiene muchos archivos con conflictos. A medida que se resuelven , se pueden agregar y realizar git statusun seguimiento de ellos.
ruido sin sentido
13

Si, como yo, lo que generalmente desea es sobrescribir el contenido del directorio de trabajo con el de los archivos escondidos, y aún tiene un conflicto, entonces lo que desea es resolver el conflicto git checkout --theirs -- .desde la raíz.

Después de eso, puede git resettraer todos los cambios del índice al directorio de trabajo, ya que aparentemente en caso de conflicto, los cambios en los archivos no conflictivos permanecen en el índice.

También es posible que desee ejecutar git stash drop [<stash name>]después, para deshacerse del alijo, porque git stash popno lo elimina en caso de conflictos.

Pedro Gimeno
fuente
2

Tenga en cuenta que Git 2.5 (Q2 2015) un futuro Git podría intentar hacer ese escenario imposible.

Ver commit ed178ef por Jeff King ( peff), 22 de abril de 2015.
(Fusionada por Junio ​​C Hamano - gitster- en commit 05c3967 , 19 de mayo de 2015)

Nota: Esto ha sido revertido. Ver abajo .

stash: requiere un índice limpio para aplicar / pop

Problema

Si ha contenido contenido en su índice y ejecuta " stash apply/pop", podemos encontrar un conflicto y poner nuevas entradas en el índice.
Recuperarse a su estado original es difícil en ese punto, porque herramientas como "git reset --keep" eliminarán cualquier cosa organizada .

En otras palabras:

" git stash pop/apply" se olvidó de asegurarse de que no solo el árbol de trabajo esté limpio, sino que también el índice esté limpio.
Esto último es importante ya que una aplicación oculta puede entrar en conflicto y el índice se utilizará para la resolución de conflictos.

Solución

Podemos hacer esto más seguro al negarnos a aplicar cuando hay cambios por etapas.

Eso significa que si hubo fusiones antes debido a la aplicación de un alijo en archivos modificados (agregados pero no confirmados), ahora no habría ninguna fusión porque el alijo aplicar / pop se detendría inmediatamente con:

Cannot apply stash: Your index contains uncommitted changes.

Obligarlo a confirmar los cambios significa que, en caso de fusiones, puede restaurar fácilmente el estado inicial (antes git stash apply/pop) con un git reset --hard.


Ver commit 1937610 (15 de junio de 2015), y commit ed178ef (22 de abril de 2015) por Jeff King ( peff) .
(Fusionada por Junio ​​C Hamano - gitster- en commit bfb539b , 24 jun 2015)

Esa confirmación fue un intento de mejorar la seguridad de la aplicación de un alijo, porque el proceso de la aplicación puede crear entradas de índice en conflicto, después de lo cual es difícil restaurar el estado del índice original.

Desafortunadamente, esto perjudica algunos flujos de trabajo comunes en torno a " git stash -k", como:

git add -p       ;# (1) stage set of proposed changes
git stash -k     ;# (2) get rid of everything else
make test        ;# (3) make sure proposal is reasonable
git stash apply  ;# (4) restore original working tree

Si "git commit" entre los pasos (3) y (4), entonces esto simplemente funciona. Sin embargo, si estos pasos son parte de un enlace previo a la confirmación, no tiene esa oportunidad (debe restaurar el estado original independientemente de si las pruebas pasaron o no).

VonC
fuente