Cómo recuperar cambios no comprometidos guardados


Tuve algunos cambios sin confirmar en mi rama de desarrollo y los guardé usando git stash, pero hubo algunos cambios que fueron muy importantes entre los que se guardaron. ¿Hay alguna manera de recuperar esos cambios?

Además, he hecho algunos cambios en la parte superior de los archivos de código almacenados desde entonces.

¿Hay alguna posibilidad de que pueda recuperar los cambios guardados en una nueva rama si es posible?

 437
Author: Flimzy, 2013-09-25

3 answers

La respuesta fácil a la pregunta fácil es git stash apply

Simplemente echa un vistazo a la rama en la que quieres tus cambios, y luego git stash apply. Luego use git diff para ver el resultado.

Después de que haya terminado con sus cambios-el apply se ve bien y está seguro de que ya no necesita el alijo-entonces use git stash drop para deshacerse de él.

Siempre sugiero usar git stash apply en lugar de git stash pop. La diferencia es que apply deja el alijo para volver a probar fácilmente el apply, o para mirando, etc. Si pop es capaz de extraer el alijo, inmediatamente también lo hará drop, y si de repente te das cuenta de que querías extraerlo en otro lugar (en una rama diferente), o con --index, o algo así, eso no es tan fácil. Si apply, usted elegir cuándo drop.

Sin embargo, todo es bastante menor de una manera u otra, y para un novato en git, debería ser más o menos lo mismo. (Y usted puede saltar todo el resto de esto!)


Y si ¿estás haciendo cosas más avanzadas o más complicadas?

Hay al menos tres o cuatro "formas diferentes de usar git stash", por así decirlo. Lo anterior es para "camino 1", el "camino fácil":

  1. Comenzó con una rama limpia, estaba trabajando en algunos cambios, y luego se dio cuenta de que los estaba haciendo en la rama incorrecta. Solo desea tomar los cambios que tiene ahora y" moverlos " a otra rama.

    Este es el caso fácil, descrito anteriormente. Ejecutar git stash save (o simple git stash, lo mismo). Echa un vistazo a la otra rama y usa git stash apply. Esto hace que git se fusione en tus cambios anteriores, usando el poderoso mecanismo de fusión de git. Inspeccione los resultados cuidadosamente (con git diff) para ver si le gustan, y si lo hace, use git stash drop para soltar el alijo. ¡Has terminado!

  2. Iniciaste algunos cambios y los escondiste. Luego cambiaste a otra rama e iniciaste más cambios, olvidando que tenías los guardados.

    Ahora quieres para mantener, o incluso mover, estos cambios, y aplica tu alijo también.

    De hecho, puede git stash save de nuevo, ya que git stash hace una "pila" de cambios. Si haces eso tienes dos escondites, uno solo llamado stash-pero también puedes escribir stash@{0}-y otro escrito stash@{1}. Use git stash list (en cualquier momento) para verlas todas. El más nuevo es siempre el número más bajo. Cuando git stash drop, se cae el más nuevo, y el que era stash@{1} se mueve a la parte superior de la pila. Si tuvieras aún más, el único eso fue stash@{2} se convierte en stash@{1}, y así sucesivamente.

    Puedes apply y luego drop un alijo específico, también: git stash apply stash@{2}, y así sucesivamente. Dejando caer un alijo específico, renumbers solo los números más altos. De nuevo, el que no tiene número es también stash@{0}.

    Si acumulas muchos escondites, puede ser bastante desordenado (¿era el escondite que quería stash@{7} o era stash@{4}? Espera, acabo de empujar a otro, ahora son 8 y 5?). Personalmente prefiero transferir estos cambios a una nueva rama, porque ramas tienen nombres, y cleanup-attempt-in-December significa mucho más para mí que stash@{12}. (El comando git stash toma un mensaje de guardado opcional, y eso puede ayudar, pero de alguna manera, todos mis alijos terminan llamados WIP on branch.)

  3. (Extra-avanzado) Has usado git stash save -p, o cuidadosamente git add-ed y/o git rm-ed bits específicos de tu código antes de ejecutar git stash save. Tenía una versión en el área de index/staging escondida, y otra versión (diferente) en el árbol de trabajo. Quieres preservar todo esto. Así que ahora use git stash apply --index, y eso a veces falla con:

    Conflicts in index.  Try without --index.
    
  4. Estás usando git stash save --keep-index para probar "lo que se va a cometer". Esta está más allá del alcance de esta respuesta; vea esta otra respuesta de StackOverflow en su lugar.

Para casos complicados, recomiendo comenzar en un directorio de trabajo "limpio" primero, confirmando cualquier cambio que tenga ahora (en una nueva rama si lo desea). De esa manera, el "en algún lugar" que los está aplicando, no tiene nada más en lo, y usted sólo va a probar los cambios guardados:

git status               # see if there's anything you need to commit
                         # uh oh, there is - let's put it on a new temp branch
git checkout -b temp     # create new temp branch to save stuff
git add ...              # add (and/or remove) stuff as needed
git commit               # save first set of changes

Ahora estás en un punto de partida "limpio". O tal vez va más como esto:

git status               # see if there's anything you need to commit
                         # status says "nothing to commit"
git checkout -b temp     # optional: create new branch for "apply"
git stash apply          # apply stashed changes; see below about --index

Lo principal a recordar es que el "stash" es un commit, es solo un commit ligeramente "divertido/raro" que no está "en una rama". La operación apply mira lo que ha cambiado la confirmación, e intenta repetirlo donde quiera que esté ahora. El alijo todavía estará allí (apply lo mantiene alrededor), por lo que puede mirarlo más, o decidir este era el lugar equivocado para apply e intentarlo de nuevo de manera diferente, o lo que sea.


Cada vez que tengas un alijo, puedes usar git stash show -p para ver una versión simplificada de lo que hay en el alijo. (Esta versión simplificada solo mira los cambios del" árbol de trabajo final", no los cambios del índice guardado que --index restaura por separado.) El comando git stash apply, sin --index, solo intenta hacer esos mismos cambios en su directorio de trabajo ahora.

Esto es cierto incluso si ya tengo algunos cambios. El comando apply se complace en aplicar un alijo a un directorio de trabajo modificado (o al menos, intentar aplicarlo). Puedes, por ejemplo, hacer esto:

git stash apply stash      # apply top of stash stack
git stash apply stash@{1}  # and mix in next stash stack entry too

Puede elegir el orden "aplicar" aquí, seleccionando escondites particulares para aplicar en una secuencia particular. Tenga en cuenta, sin embargo, que cada vez que básicamente está haciendo un "git merge", y como advierte la documentación de merge:

Ejecutar git merge con cambios no triviales no comprometidos es desanimado: si bien es posible, puede dejarlo en un estado que es difícil para retroceder en caso de conflicto.

Si comienza con un directorio limpio y solo está haciendo varias operaciones git apply, es fácil retroceder: use git reset --hard para volver al estado limpio y cambie sus operaciones apply. (Es por eso que recomiendo comenzar en un directorio de trabajo limpio primero, para estos casos complicados.)


¿Qué pasa con lo peor posible caso?

Digamos que estás haciendo Muchas Cosas Avanzadas de Git, y has creado un stash, y quieres git stash apply --index, pero ya no es posible aplicar el stash guardado con --index, porque la rama ha divergido demasiado desde el momento en que lo guardaste.

Para esto es git stash branch.

Si usted:

  1. echa un vistazo a la confirmación exacta en la que estabas cuando hiciste el original stash, luego
  2. crear una nueva rama, y por último
  3. git stash apply --index

El intento de recrear los cambios definitivamente funcionará. Esto es lo que hace git stash branch newbranch. (Y luego deja caer el alijo ya que se aplicó con éxito.)


Algunas palabras finales sobre --index (¿qué diablos es esto?)

Lo que el --index hace es simple de explicar, pero un poco complicado internamente:

  • Cuando usted tiene cambios, usted tiene que git add (o "etapa") antes de commiting.
  • Así, al ejecutar git stash, es posible que haya editado ambos archivosfoo y zorg, pero solo organizó uno de ellos.
  • Así que cuando pides recuperar el alijo, podría ser bueno si git add es el add ed cosas y hace no git add las cosas no añadidas. Es decir, si add ed foo pero no zorg antes de hacer el stash, podría ser bueno tener exactamente la misma configuración. Lo que fue escenificado, debe ser escenificado de nuevo; lo que fue modificado pero no escenificado, debe ser modificado pero no preparado.

La bandera --index para apply intenta configurar las cosas de esta manera. Si su árbol de trabajo está limpio, esto generalmente solo funciona. Si su árbol de trabajo ya tiene cosas added, sin embargo, puede ver cómo podría haber algunos problemas aquí. Si omite --index, la operación apply no intenta conservar toda la configuración preparada/no preparada. En su lugar, solo invoca la maquinaria merge de git, usando el work-tree commit en el "stash bag". Si no cuidarse de preservar staged / unstaged, omitiendo --index hace que sea mucho más fácil para git stash apply hacer su trabajo.

 727
Author: torek,
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-05-23 12:18:15
git stash pop

Tendrá todo de nuevo en su lugar

Como se sugiere en los comentarios, puede usar git stash branch newbranch para aplicar el alijo a una nueva rama, que es lo mismo que ejecutar:

git checkout -b newbranch
git stash pop
 37
Author: Stefano Falasca,
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-06-14 08:35:42

Para hacer esto simple, tienes dos opciones para volver a aplicar tu alijo:

  1. git stash pop - Restaurar de nuevo al estado guardado, pero elimina el alijo del almacenamiento temporal.
  2. git stash apply - Restaurar de nuevo al estado guardado y deja la lista de alijo para su posible reutilización posterior.

Puedes leer con más detalle sobre git stashes en este artículo.

 5
Author: Nesha Zoric,
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-05-25 07:49:29