2012-01-25 18 views
19

Hemos hecho algo malo.`git stash` durante un conflicto de combinación

Hemos ejecutado git stash save durante un conflicto de combinación, y ahora no podemos restaurar nuestro trabajo.

cosas que hemos probado:

git pull -Xours origin master 
git stash apply --index 

Y:

git pull origin master 
git stash save --keep-index "merge conflicts" 
git stash apply [email protected]{1} 

Por favor, ayuda!

+0

¿Hiciste realmente algo significativo? (¿De verdad necesita restaurar los cambios escondidos?) ¿Puede restablecer el intento de fusión, y hacerlo de nuevo? – Cascabel

+1

Sí y no, respectivamente. Los cambios consisten en más de un día de resolución de conflicto de fusión. – bukzor

+3

@bukzor: si necesita más de un día para fusionar la resolución de conflictos, podría ser hora de reconsiderar sus políticas con respecto a la gestión de sucursales y la distribución del trabajo (o la frecuencia de fusión). Dichas resoluciones de fusión prolongadas son, después de todo, una buena fuente de errores difíciles de encontrar debido a la cantidad de cambios realizados en una confirmación – Grizzly

Respuesta

0

Cuando se encuentre en un estado conflictivo (índice y directorio de trabajo), no podrá hacer git stash - dará error al anotar las entradas no fusionadas.

Asegúrate de que realmente has hecho un alijo. Ver la salida de git stauts y git stash show

+0

Antes de 'git stash', he resuelto los conflictos y procedo a usar' git add'. Fue después de que 'git add' mis resoluciones, hice más ediciones y luego hice un' git stash save msg'. Entonces eso tuvo éxito. –

+0

@bukzor en realidad, acabo de probar esto con msysgit 1.8.3 en Windows 7. Si el archivo se deja en conflicto (es decir, no se ha intentado resolver el conflicto de fusión), entonces 'git stash save' aborta, sin escondiendo el archivo conflictivo. Así que *** esto es realmente correcto, no es falso ***. –

18

El problema parece ser que git stash no guarda una referencia a la rama que estaba tratando de fundirse en. Durante una combinación, esta se almacena en una ref llamado MERGE_HEAD.

Para solucionarlo y volver a su estado anterior, debe encontrar la revisión (supongamos que es d7a9884a380f81b2fbf002442ee9c9eaf34ff68d) que estaba intentando fusionar y configurar MERGE_HEAD después de aplicar el alijo.

continuación, puede aplicar el alijo (con --index para volver a la etapa, todo lo que fue efectuado antes), y establecer su MERGE_HEAD:

git stash apply --index 
git update-ref MERGE_HEAD d7a9884a380f81b2fbf002442ee9c9eaf34ff68d 
+0

Si bien lo anterior me parece cierto, no estoy del todo seguro de que basta con configurar MERGE_HEAD y eliminar el contenido para restablecer el estado de fusión. Me mantendría alejado del uso de git stash durante los conflictos, si es posible. – user1338062

+1

Yo también lo haría, pero eso es una retrospectiva en este punto. – bukzor

1

Dada su último comentario: se puede usar

git stash megre --no-commit <branch> 

para poner el índice en un estado de "fusión" sin cometer los cambios

luego modificarla con lo que quiere:

si ya ha elaborado su combinación en el alijo:

git reset #to remove the "conflicts" flags 
git checkout <initial commit> -- ./ #to revert everything to the previous working state, 
git stash apply #apply your changes 

y una vez que todo está en el estado deseado, git commit


Acerca comentario bukzor 's: en realidad hay una gran diferencia entre git checkout <tree-ish> y git checkout <tree-ish> -- <files>.

Desde el reference en git checkout:

  • git checkout <branch>: Esta forma cambia ramas mediante la actualización del índice, trabajando árbol, y la cabeza a reflejar la rama especificada o cometen.

  • git checkout [-p|--patch] <tree-ish> -- <pathspec>: Cuando se proporcionan <rutas> o --patch, git checkout no cambia de ramas. Actualiza las rutas de acceso especificadas en el árbol de trabajo desde el archivo de índice o desde un nombre < tree-ish > (lo más frecuente es una confirmación).

git checkout <initial commit> De hecho, descartar la información de fusión.

git checkout <initial commit> -- ./ (tenga en cuenta el extra -- ./), por el contrario, mantendrá la información de combinación, y revertir todos los archivos de seguimiento a su estado en <initial commit>.

+0

'git checkout' eliminará el estado de fusión, ¿no?Terminaré con una confirmación normal que duplica todos los cambios en el maestro. – bukzor

+0

'git stash apply' también borra el estado de fusión, estableciendo explícitamente la referencia MERGE_HEAD tal como se sugirió en la respuesta de Evan, el truco para mí –

+0

En git 2, no hay ningún comando como' git stash merge' :( – dcorking

1

Hice lo mismo hoy, y tomé un enfoque diferente (después de la prueba y el error) para volver al estado justo antes de esconderme para poder continuar resolviendo conflictos y completar la fusión.

Primero, después de eliminar la fusión parcial en la rama de destino, capturé una lista de los archivos con los conflictos restantes (archivo de texto o pestaña del editor). Esta es solo la lista de archivos sin grabar luego de eliminarla, ya que los archivos con conflictos ya resueltos se habrían configurado antes del bloqueo.

$ git status 
# Changes not staged for commit: 
# (use "git add <file>..." to update what will be committed) 
# (use "git checkout -- <file>..." to discard changes in working directory) 
# 
# modified: myproject/src/main/java/com/acme/package3/Class3.java 
# modified: myproject/src/main/java/com/acme/package3/Class4.java 
# 

A continuación, he creado un parche y restablecer la rama de nuevo al estado de pre-fusión:

$ git diff HEAD > ~/merge-with-resolved-conflicts.patch 
$ git reset --hard HEAD 

Entonces creó una rama temporal (derivado de la rama de destino de combinación), y se aplica el parche:

$ git checkout -b my-temp-branch 
$ git apply ~/merge-with-resolved-conflicts.patch 
$ git commit -a -m "Merge with resolved conflicts" 

manera que la cabeza de mi-temp-rama ahora contiene todo lo que se fusionó, incluyendo los archivos con conflictos resueltos, y los archivos con conflictos restantes.

Entonces cambió de nuevo a la rama original, se fusionó de nuevo, y se veía en el estado git

$ git checkout my-branch 
$ git merge other-branch 
$ git status 

El estado muestra la lista completa de los archivos con conflictos:

# Unmerged paths: 
# (use "git add <file>..." to mark resolution) 
# 
# both modified:  myproject/src/main/java/com/acme/package1/Class1.java 
# both modified:  myproject/src/main/java/com/acme/package2/Class2.java 
# both modified:  myproject/src/main/java/com/acme/package3/Class3.java 
# both modified:  myproject/src/main/java/com/acme/package3/Class4.java 
# 

Ahora Necesitaba compare estas dos listas de archivos. Cualquier archivo en la segunda lista pero no el primero ya se había resuelto (en este ejemplo, Class1.java y Class2.java). Así que para cada uno de esos archivos, tiré en la versión con conflictos resueltos de la rama temporal (como la cereza-escoge, pero para archivos individuales en lugar de un envío entero):

$ git checkout my-temp-branch myproject/src/main/java/com/acme/package1/Class1.java 
$ git checkout my-temp-branch myproject/src/main/java/com/acme/package2/Class2.java 

Una vez hecho esto, yo estaba de vuelta al estado anterior al alijo, para poder reanudar la resolución de los conflictos restantes y comprometer la fusión.

0

Mi solución para salir de esta (pop alijo git durante un conflicto de combinación) fue:

  • crear, y obtenga una nueva (local) rama mytemporarybranch

    mytemporarybranch git branch & & git checkout mytemporarybranch

  • cometen en este mytemporarybranch

    git commit -m "mi fusión desordenado y calabaza"

  • la caja myoriginalbranch

    git checkout myoriginalbranch

  • fusión correctamente (sin pop calabaza/se aplica este momento!)

  • calabaza fusionar el mytemporarybranch a la rama myoriginal

    git fusionar mytemporarybranch --squash

Cuestiones relacionadas