Deshacer git stash pop accidental

186

Guardé algunos cambios locales antes de hacer una fusión complicada, hice la fusión, y luego olvidé estúpidamente antes de ejecutar git stash pop. El pop creó algunos problemas (llamadas a métodos incorrectos en una gran base de código) que están resultando difíciles de rastrear. Corrí git stash show, así que al menos sé qué archivos se cambiaron. Si nada más, supongo que esta es una lección para comprometerse más.

Mi pregunta: ¿es posible deshacer el stash pop sin deshacer también la fusión?

nren
fuente
2
Se supone que no debes permitirte git stash popsin comprometerte primero. ¿Qué hiciste para lograr eso?
Chris Jester-Young
No estoy seguro de ser honesto (esto fue ayer). La fusión no se comprometió por sí sola porque hubo conflictos. De alguna manera pude ejecutar stash pop después de eso.
nren
1
Hice esto solo sé usando git versión 1.7.9.msysgit.0. Tenía archivos sin escena y el stash pop simplemente fusionó todo.
PandaWood
Pude ejecutar git stash popdespués de organizar los cambios (aunque no me comprometí) con la versión 2.25.0.windows.1 de git
Artem Hevorhian
Si indexó sus cambios y los perdió mientras corría stash pop/applyantes de realizar una confirmación, puede disparar git fsck --lost-found. Este comando iterará a través de los blobs colgantes (archivos reales para aquellos que no están familiarizados con la terminología de git) que se organizaron pero no se comprometieron en ningún lugar (por lo tanto, colgando), y los colocará en el directorio .git / lost-found / , donde puede git showverlos si estos son los archivos que estás buscando.
Artem Hevorhian

Respuestas:

69

Intenta usar ¿Cómo recuperar un alijo caído en Git? para encontrar el alijo que metiste. Creo que siempre hay dos confirmaciones para un alijo, ya que conserva el índice y la copia de trabajo (a menudo la confirmación del índice estará vacía). Luego git show, para ver la diferencia y utilizar patch -Rpara no aplicarlos.

Ben Jackson
fuente
66
Wow eso funcionó. Pude encontrar las confirmaciones de escondite con git fsck --no-reflog | awk '/dangling commit/ {print $3}'(desde el enlace), y solo encontré manualmente el problema de esa diferencia. ¡Gracias!
nren
1
El fsck genera una lista enorme. Es tedioso mostrar todos los SHA1 que hay. Cómo haces esto ?
meson10
55
@ meson10: Desafortunadamente, los escondites se guardan en un registro, lo cual sería la manera obvia (si fueran una rama real) de mirar el historial de los escondites reventados. También permítanme sugerir que un voto negativo + solicitud de ayuda no es la mejor estrategia.
Ben Jackson
2
Me tomó un poco de trabajo para hacerlo bien. Aquí está el resultado de mi trabajo git diff -p ${STACH_SHA1}~1 ${STASH_SHA1} | patch -R -p1:; Intenté con git showlo sugerido, pero su salida no fue buena para el parche; También tuve que proporcionar la -p1opción de parchear para quitar el elemento a/..y b/..que se git diffcoloca delante de los archivos, de lo contrario no resolvería las rutas desde la raíz del repositorio. SUGERENCIA: tenga cuidado y cometa el desastre en una rama separada antes de jugar con el parche.
basilikode
@BenJackson En su respuesta "siempre" significa ambos stash popy stash pushactivará una confirmación que guardaría los cambios en el índice y el directorio de trabajo, ¿verdad?
Artem Hevorhian
36

De git stash --help

Recovering stashes that were cleared/dropped erroneously
   If you mistakenly drop or clear stashes, they cannot be recovered through the normal safety mechanisms. However, you can try the
   following incantation to get a list of stashes that are still in your repository, but not reachable any more:

       git fsck --unreachable |
       grep commit | cut -d\  -f3 |
       xargs git log --merges --no-walk --grep=WIP

Esto me ayudó mejor que la respuesta aceptada con el mismo escenario.

kachar
fuente
13
Tenga en cuenta que muchas soluciones que implican la búsqueda de "WIP" se basan en los mensajes de ocultación predeterminados. Si le da a sus reservas mensajes explícitos, es posible que no contengan WIP.
Ben Jackson
Gracias. Agregué la opción --oneline al comando de registro para mejorar la legibilidad.
basslo
Esto solo le ayuda a encontrar el SHA de la confirmación de almacenamiento. Pero si se integra con el comentario @basilikode de la respuesta aceptada (git diff SHA ~ 1 SHA | patch -R), funciona bien. Recomiendo usar path --dry-run primero para verificar.
Jarek C
3

Si su fusión no fuera demasiado complicada, otra opción sería:

  1. Mueva todos los cambios, incluidos los cambios de combinación, de nuevo a alijo utilizando "git stash"
  2. Ejecute la fusión nuevamente y confirme los cambios (sin los cambios del alijo oculto)
  3. Ejecute un "git stash pop" que debería ignorar todos los cambios de su fusión anterior ya que los archivos son idénticos ahora.

Después de eso, solo le quedan los cambios del alijo que dejó caer demasiado pronto.

Markus
fuente