Abortar un pop de stash en Git


Abrí un alijo y hubo un conflicto de fusión. A diferencia de la pregunta que aparece como un duplicado, ya tenía algunos cambios sin confirmar en el directorio que quería mantener. No solo quiero hacer que el conflicto de fusión desaparezca, sino también que mi directorio vuelva al estado que estaba antes del pop.

Probé git merge --abort, pero git afirmó que no había fusión en curso. ¿Hay una manera fácil de abortar un pop sin destruir los cambios que originalmente tenía en el directorio?

 179
Author: Casebash, 2011-12-15

12 answers

Ok, creo que he resuelto "git stash unapply". Es más complejo que git apply --reverse porque necesita una acción de fusión inversa en caso de que haya alguna fusión realizada por git stash apply.

La fusión inversa requiere que todos los cambios actuales se introduzcan en el índice:

  • git add -u

Luego invierte el merge-recursive que fue hecho por git stash apply:

  • git merge-recursive stash@{0}: -- $(git write-tree) stash@{0}^1

Ahora te quedarás solo con los cambios que no son de stash. Estarán en el índice. Puedes use git reset para eliminar la escena de los cambios si lo desea.

Dado que su git stash apply original falló, asumo que lo contrario también podría fallar ya que algunas de las cosas que quiere deshacer no se hicieron.

Aquí hay un ejemplo que muestra cómo la copia de trabajo (a través de git status) termina limpia de nuevo:

 $ git status
# On branch trunk
nothing to commit (working directory clean)
 $ git stash apply
Auto-merging foo.c
# On branch trunk
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   foo.c
#
no changes added to commit (use "git add" and/or "git commit -a")
 $ git add -u
 $ git merge-recursive stash@{0}: -- $(git write-tree) stash@{0}^1
Auto-merging foo.c
 $ git status
# On branch trunk
nothing to commit (working directory clean)
 37
Author: Ben Jackson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-22 01:32:04

Mi caso de uso: acabo de intentar aparecer en la rama equivocada y tengo conflictos. Todo lo que necesito es deshacer el pop pero mantenerlo en la lista de alijo para que pueda pop en la rama correcta. Hice esto:

git reset HEAD --hard
git checkout my_correct_branch
git stash pop

Fácil.

 162
Author: jmoz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-07 16:16:48

Editar: De la documentación git help stash en la sección pop:

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

Si se usa la opción index index, entonces intenta restablecer no solo los cambios del árbol de trabajo, sino también los del índice. Sin embargo, esto puede fallar, cuando tiene conflictos (que se almacenan en el índice, donde por lo tanto no puede ya aplicar los cambios como eran originalmente).

Intenta copiar todo tu repositorio en un nuevo dir (para que tengas una copia del mismo) y ejecuta:

git stash show y guarda esa salida en algún lugar si te importa.

Luego: git stash drop para soltar el alijo en conflicto entonces: git reset HEAD

Eso debería dejar su repositorio en el estado que estaba antes (con suerte, todavía no he sido capaz de reprogramar su problema)

===

Estoy tratando de repro su problema, pero todo lo que consigo cuando usin git stash pop es:

error: Your local changes to the following files would be overwritten by merge:
...
Please, commit your changes or stash them before you can merge.
Aborting

En un dir limpio:

git init
echo hello world > a
git add a & git commit -m "a"
echo hallo welt >> a
echo hello world > b
git add b & git commit -m "b"
echo hallo welt >> b
git stash
echo hola mundo >> a
git stash pop

No veo que git intente fusionar mis cambios, simplemente falla. ¿Tiene algún paso de repro que podamos seguir para ayudarlo?

 41
Author: DavidG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-19 04:18:50

Si no tienes que preocuparte por ningún otro cambio que hayas hecho y solo quieres volver a la última confirmación, entonces puedes hacer:

git reset .
git checkout .
git clean -f
 5
Author: hugo der hungrige,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-26 13:24:40

OK, creo que he logrado encontrar un flujo de trabajo que te llevará de vuelta a donde necesitas estar (como si no hubieras hecho el pop).

TOME UNA COPIA DE SEGURIDAD DE ANTEMANO!! No se si esto funcionará para usted, así que copie todo su repositorio por si acaso no funciona.

1) Solucione los problemas de fusión y solucione todo el conflicto seleccionando todos los cambios que vienen del parche (en tortoisemerge, esto aparece como uno solo.REMOETE (de ellos)).

git mergetool

2) Confirmar estos cambios (que ya se añadirá mediante el comando mergetool). Dale un mensaje de confirmación de "fusionar" o algo que recuerdes.

git commit -m "merge"

3) Ahora todavía tendrá sus cambios locales no escalonados que comenzó originalmente, con una nueva confirmación del parche (podemos deshacernos de esto más adelante). Ahora confirma tus cambios no escalonados

git add .
git add -u .
git commit -m "local changes"

4) Invierta el parche. Esto se puede hacer con el siguiente comando:

git stash show -p | git apply -R

5) Confirme estos cambios:

git commit -a -m "reversed patch"

6) Deshágase del parche/desempaquete commits

git rebase -i HEAD^^^

De esto, elimine las dos líneas con 'merge' y 'reversed patch'.

7) Recupere sus cambios no cambiados y deshaga la confirmación de 'cambios locales'

git reset HEAD^

Lo he repasado con un ejemplo simple y te lleva de vuelta a donde quieres estar - directamente antes de que el alijo fuera popeado, con tus cambios locales y con el alijo todavía disponible para pop.

 4
Author: agentgonzo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-22 17:08:05

Resolví esto de una manera algo diferente. Esto es lo que pasó.

Primero, me metí en la rama equivocada y tuve conflictos. El alijo permaneció intacto, pero el índice estaba en resolución de conflictos, bloqueando muchos comandos.

Un simple git reset HEAD abortó la resolución de conflictos y dejó los cambios no comprometidos (y NO DESEADOS).

Varios git co <filename> revirtieron el índice al estado inicial. Finalmente, cambié la rama con git co <branch-name> y ejecuté una nueva git stash pop, que se resolvió sin conflicto.

 3
Author: pid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-20 16:08:14

Algunas ideas:

  • Use git mergetool para dividir los archivos merge en partes originales y nuevas. Esperemos que uno de ellos es el archivo con sus cambios no-alijo en él.

  • Aplica la diferencia del alijo al revés, para deshacer solo esos cambios. Probablemente tendrá que dividir manualmente los archivos con los conflictos de fusión (que con suerte el truco anterior funcionará).

No probé ninguno de estos, así que no estoy seguro de que funcionarán.

 2
Author: asmeurer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-15 10:29:52

Usa git reflog para listar todos los cambios realizados en tu historial de git. Copie un id de acción y escriba git reset ACTION_ID

 1
Author: Fatih,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-16 01:43:15

Podría reproducir clean git stash pop en el directorio "dirty", con cambios sin confirmar, pero aún no pop que genera un conflicto de fusión.

Si en el conflicto de fusión el alijo que intentó aplicar no desapareció, puede intentar examinar git show stash@{0} (opcionalmente con --ours o --theirs) y comparar con git statis y git diff HEAD. Debería ser capaz de ver qué cambios vinieron de la aplicación de un alijo.

 1
Author: Jakub Narębski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-18 19:32:16

Si DavidG está en lo cierto de que no hizo estallar el alijo debido al conflicto de fusión, entonces simplemente necesita limpiar su directorio de trabajo. Rápidamente git commit todo lo que te importa. (Puedes reset o squash la confirmación más tarde si no has terminado.) Luego con todo lo que te importa safe, git reset todo lo demás que git stash pop volcó en tu directorio de trabajo.

 1
Author: robrich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-19 19:32:42

Si no hubo cambios escalonados antes de git stash pop, como en la pregunta, entonces los siguientes dos comandos deberían funcionar.

git diff --name-only --cached | xargs git checkout --ours HEAD
git ls-tree stash@{0}^3 --name-only | xargs rm

La primera invierte cualquier fusión del alijo, exitosa o no. El segundo elimina cualquier archivo no rastreado introducido por el alijo.

Desde man git stash : The working directory must match the index. Lo que @DavidG señala, el stash pop fallará si hay algún conflicto de archivos modificados no escalonados actualmente. Como tal, no deberíamos tener que preocuparnos por resolver conflictos de fusión más allá de volver a HEAD. Los archivos modificados restantes no están relacionados con el alijo, y se modificaron antes del stash pop

Si hubo cambios por etapas, no estoy claro si podemos confiar en los mismos comandos y es posible que desee probar la técnica de @Ben Jackson. Sugerencias apreciadas..

Aquí hay una configuración de prueba para todos los diversos casos https://gist.github.com/here/4f3af6dafdb4ca15e804

# Result:
# Merge succeeded in m (theirs)
# Conflict in b
# Unstaged in a
# Untracked in c and d

# Goal:
# Reverse changes to successful merge m
# Keep our version in merge conflict b
# Keep our unstaged a
# Keep our untracked d
# Delete stashed untracked c
 0
Author: here,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-01 05:46:39

Estoy publicando aquí con la esperanza de que otros mi encontrar mi respuesta útil. Tuve un problema similar cuando traté de hacer un stash pop en una rama diferente a la que había escondido desde. En mi caso, no tenía archivos que no estuvieran comprometidos o en el índice, pero aún así me metí en el caso de conflictos de fusión (el mismo caso que @pid). Como otros señalaron anteriormente, el pop de git stash fallido retuvo mi stash, luego un rápido git reset HEAD más volver a mi rama original y hacer el stash desde allí lo hizo resolver mi problema.

 0
Author: Victor Camacho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-14 22:47:37