Pregunta

Frecuentemente uso git stash y git stash pop guardar y restaurar los cambios en mi árbol de trabajo.Ayer tuve algunos cambios en mi árbol de trabajo que me había escondido y se metió, y luego me hizo más cambios en mi árbol de trabajo.Me gustaría volver atrás y revisar de ayer guardados los cambios, pero git stash pop parece quitar todas las referencias a la confirmación asociado.

Sé que si yo uso git stash entonces .git/refs/stash contiene la referencia de la confirmación se utiliza para crear el alijo.Y .git/logs/refs/stash contiene toda la mercancía.Pero esas referencias se han ido después de git stash pop.Sé que la confirmación está todavía en mi repositorio en algún lugar, pero no sé lo que era.

Hay una manera fácil de recuperar de ayer alijo de cometer referencia?

Tenga en cuenta que esto no es crítico para mí el día de hoy porque tengo copias de seguridad diarias y puede ir en el día de ayer del árbol de trabajo para conseguir mis cambios.Estoy preguntando, porque debe haber una manera más fácil!

¿Fue útil?

Solución

Una vez que usted sabe el hash de la mercancía a comprometerse caído, usted puede aplicar como un clavo:

git stash apply $stash_hash

O bien, puede crear una rama separada con

git branch recovered $stash_hash

Después de eso, usted puede hacer lo que quiera con todas las herramientas normales.Cuando hayas terminado, acaba de golpe la rama de distancia.

Encontrar el hash

Si acaba de estallar y el terminal todavía está abierta, se le todavía tiene el valor de hash impreso por git stash pop en la pantalla (gracias, Dolda).

De lo contrario, usted puede encontrar que el uso de esta para Linux, Unix o Git Bash para Windows:

git fsck --no-reflog | awk '/dangling commit/ {print $3}'

...o con el uso de Powershell de Windows:

git fsck --no-reflog | select-string 'dangling commit' | foreach { $bits = $_ -split ' '; echo $bits[2];}

Esto le mostrará todas las comete en los consejos de su confirmación gráfico que ya no se hace referencia de cualquier rama o etiqueta de cada perdió cometer, incluso cada alijo de cometer alguna vez has creado, será en algún lugar en ese gráfico.

La forma más fácil de encontrar el escondite de cometer desea es probablemente pasar la lista a gitk:

gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )

...o ver la respuesta de emragins si el uso de Powershell de Windows.

Esto lanzará un navegador de repositorios, mostrando cada commit en el repositorio de siempre, independientemente de si es accesible o no.

Puede reemplazar gitk allí con algo como git log --graph --oneline --decorate si usted prefiere un buen gráfico de la consola a través de una separada de la GUI de la aplicación.

A punto de alijo se compromete, busque los mensajes de confirmación de esta forma:

WIP en somebranch: commithash Algunos viejos mensaje de confirmación

Nota:El mensaje del commit sólo será en este formulario (comenzando con "WIP en") si no el suministro de un mensaje cuando usted hizo git stash.

Otros consejos

Si no cerca de la terminal, con tan sólo mirar en la salida de git stash pop y usted tendrá el IDENTIFICADOR de objeto del caído alijo.Que normalmente se ve como esto:

$ git stash pop
[...]
Dropped refs/stash@{0} (2ca03e22256be97f9e40f08e6d6773c7d41dbfd1)

(Tenga en cuenta que git stash drop también se produce la misma línea.)

Para conseguir que el alijo de nuevo, sólo tiene que ejecutar git branch tmp 2cae03e, y se obtendrá como una rama.Para convertir esto en una carpeta, ejecute:

git stash apply tmp
git stash

Como una rama también permite manipular libremente;por ejemplo, cherry-pick o combinar.

Sólo quería hablar de esta adición a la aceptación de la solución.No era inmediatamente obvio para mí la primera vez que probé este método (tal vez debería haber sido), pero para aplicar el alijo de el valor de hash, sólo tiene que utilizar "git stash apply ":

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

Cuando yo era nuevo en git, este no estaba claro para mí, y yo estaba tratando de diferentes combinaciones de "git show", "git apply", "parche", etc.

Para obtener la lista de los escondites que todavía están en el repositorio, pero no puede llegar a más:

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

Si usted le dio un título a su escondite, reemplazar "WIP" en -grep=WIP al final del comando, con una parte de su mensaje, por ejemplo, -grep=Tesselation.

El comando es grepping para "WIP" porque el valor predeterminado del mensaje de confirmación para un alijo está en la forma WIP on mybranch: [previous-commit-hash] Message of the previous commit.

He construido un comando que me ayudó a encontrar mi perdido alijo de cometer:

for ref in `find .git/objects | sed -e 's#.git/objects/##' | grep / | tr -d /`; do if [ `git cat-file -t $ref` = "commit" ]; then git show --summary $ref; fi; done | less

Esta es una lista de todos los objetos en el .git/objects árbol, busca a los que son de tipo cometer, a continuación se muestra un resumen de cada uno de ellos.Desde este punto era sólo una cuestión de mirar a través de el se compromete a encontrar un "trabajo en CURSO sobre el trabajo:6a9bb2" ("el trabajo" es mi rama, 619bb2 es una reciente commit).

Tomo nota de que si yo uso "git stash apply" en lugar de "git stash pop" yo no tendría este problema, y si yo uso "git stash guardar mensaje"luego de la confirmación podría haber sido más fácil encontrar.

Actualización:Con Nathan idea, esta se hace más corta:

for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less

git fsck --unreachable | grep commit debe mostrar el sha1, aunque la lista se devuelve puede ser bastante grande. git show <sha1> para ver si es la confirmación que usted desea.

git cherry-pick -m 1 <sha1> se mezcla la confirmación en la rama actual.

Si desea restash perdido alijo, usted necesita encontrar el hash de su pérdida de alijo en primer lugar.

Como Aristóteles Pagaltzis sugirió un git fsck debe ayudarle.

Personalmente yo uso mi log-all alias que me indican en cada commit (recuperable compromete a) para tener una mejor vista de la situación :

git log --graph --decorate --pretty=oneline --abbrev-commit --all $(git fsck --no-reflogs | grep commit | cut -d' ' -f3)

Usted puede hacer de forma aún más rápida de búsqueda si usted está buscando sólo para "WIP en" mensajes".

Una vez que usted sabe que su sha1, simplemente cambiar su alijo reflog para agregar el viejo clavo :

git update-ref refs/stash ed6721d

Probablemente te prefieren tener asociado un mensaje para un -m

git update-ref -m "$(git log -1 --pretty=format:'%s' ed6721d)" refs/stash ed6721d

Y usted aún desea utilizar esto como un alias :

restash = !git update-ref -m $(git log -1 --pretty=format:'%s' $1) refs/stash $1

Windows PowerShell equivalente, utilizando gitk:

gitk --all $(git fsck --no-reflog | Select-String "(dangling commit )(.*)" | %{ $_.Line.Split(' ')[2] })

Probablemente hay una manera más eficiente de hacer esto en un tubo, pero esto no hace el trabajo.

Me gustó la de Aristóteles enfoque, pero no se como usar GITK...como estoy acostumbrada a usar GIT desde la línea de comandos.

En su lugar, tomé la colgantes compromete y salida el código en un archivo DIFF para revisar en mi editor de código.

git show $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' ) > ~/stash_recovery.diff

Ahora usted puede cargar hasta la resultante diff/archivo txt (en tu carpeta de inicio) en el editor de txt y ver el código real y que resulta SHA.

A continuación, sólo uso

git stash apply ad38abbf76e26c803b27a6079348192d32f52219

En OSX con git v2.6.4, sólo tengo que ejecutar git stash caer accidentalmente, luego me enteré de que por pasando a través de los pasos siguientes

Si usted conoce el nombre de la mercancía, a continuación, utilizar:

$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show | grep -B 6 -A 2 <name of the stash>

de lo contrario, usted encontrará el ID del resultado manualmente con:

$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show

Entonces, cuando usted encontrar la confirmación-id acaba de golpear el git stash apply {commit-id}

Espero que esto ayude a alguien rápidamente

¿Por qué las personas hacen esta pregunta?Debido a que todavía no conoce o entiende el reflog.

La mayoría de las respuestas a esta pregunta dan mucho tiempo comandos con opciones casi nadie se acuerda.Así que la gente venga a esta pregunta y copiar y pegar lo que ellos piensan que necesitan y se olvida casi inmediatamente después.

Yo aconsejaría a todo el mundo con esta pregunta sólo tiene que comprobar la reflog (git reflog), no mucho más que eso.Una vez que ves la lista de todos los envíos hay cientos de formas para averiguar qué cometer estás buscando y cherry-pick o la creación de una rama de ella.En el proceso usted ha aprendido acerca de la reflog y opciones útiles para diversos básica de los comandos de git.

Puedes ver la lista de todos los inalcanzable comete al escribir este comando en la terminal -

git fsck --unreachable

Compruebe inalcanzable cometer hash -

git show hash

Por último se aplica si usted encuentra el elemento escondido -

git stash apply hash

Quiero agregar a la aceptación de la solución de otra buena manera de ir a través de todos los cambios, cuando no tienes gitk disponible o no X para la salida.

git fsck --no-reflog | awk '/dangling commit/ {print $3}' > tmp_commits

for h in `cat tmp_commits`; do git show $h | less; done

Luego de obtener todos los diffs para los hash muestra una después de la otra.Pulse 'q' para llegar a la siguiente diff.

El aceptó responder por Aristóteles mostrará todos accesibles compromete, incluyendo la no-almacen-como cometa.Para filtrar el ruido:

git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
  --grep="WIP on" --min-parents=3 --max-parents=3

Esto sólo se incluyen compromete a que tienen exactamente 3 padre comete (que un alijo tendrá), y cuyo mensaje incluye "WIP en".

Tenga en cuenta, que si usted guarda su escondite con un mensaje (por ejemplo, git stash save "My newly created stash"), esto anulará el valor de "WIP en..." del mensaje.

Usted puede mostrar más información sobre cada una de cometer, por ejemplo,mostrar el mensaje de confirmación, o pasar a git stash show:

git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
  --grep="WIP on" --min-parents=3 --max-parents=3 | \
xargs -n1 -I '{}' bash -c "\
  git log -1 --format=medium --color=always '{}'; echo; \
  git stash show --color=always '{}'; echo; echo" | \
less -R

Yo no podía conseguir ninguna de las respuestas para funcionar en Windows en una simple ventana de comandos (Windows 7 en mi caso). awk, grep y Select-string no eran reconocidos como los comandos.Lo he intentado un enfoque diferente:

  • primera carrera: git fsck --unreachable | findstr "commit"
  • copiar el resultado en el bloc de notas
  • encontrar reemplazar "inalcanzable comprometerse" con start cmd /k git show

se verá algo como esto:

start cmd /k git show 8506d235f935b92df65d58e7d75e9441220537a4 start cmd /k git show 44078733e1b36962571019126243782421fcd8ae start cmd /k git show ec09069ec893db4ec1901f94eefc8dc606b1dbf1 start cmd /k git show d00aab9198e8b81d052d90720165e48b287c302e

  • guardar como .archivo bat y ejecutarlo
  • la secuencia de comandos se abrirá un montón de comandos de windows, mostrando cada commit
  • si encuentras el que estás buscando para, ejecutar: git stash apply (your hash)

puede no ser la mejor solución, pero funcionó para mí

¿Qué vine aquí buscando es cómo conseguir realmente el alijo de nuevo, independientemente de lo que yo he comprobado.En particular, me había escondido algo, entonces se comprueba una versión anterior, entonces poped, pero el alijo fue un no-op en ese momento anterior punto, por lo que el alijo desaparecido;Yo no podía hacer git stash a empujar de nuevo en la pila.Esto funcionó para mí:

$ git checkout somethingOld
$ git stash pop
...
nothing added to commit but untracked files present (use "git add" to track)
Dropped refs/stash@{0} (27f6bd8ba3c4a34f134e12fe69bf69c192f71179)
$ git checkout 27f6bd8ba3c
$ git reset HEAD^    # Make the working tree differ from the parent.
$ git stash # Put the stash back in the stack.
Saved working directory and index state WIP on (no branch): c2be516 Some message.
HEAD is now at c2be516 Some message.
$ git checkout somethingOld # Now we are back where we were.

En retrospectiva, debería haber sido el uso de git stash apply no git stash pop.Yo estaba haciendo una bisect y había un pequeño parche que yo quería aplicar en cada bisect paso.Ahora estoy haciendo esto:

$ git reset --hard; git bisect good; git stash apply
$ # Run tests
$ git reset --hard; git bisect bad; git stash apply
etc.

Recuperado mediante los siguientes pasos:

  1. Identificar los eliminados alijo de código hash:

    gitk --todos $( git fsck-no-reflog | awk '/colgando commit/ {print $3}' )

  2. Escoger el Clavo:

    git cherry-pick -m 1 $stash_hash_code

  3. Resolver Conflictos si los hubiere, mediante:

    git mergetool

Además, usted puede estar teniendo problemas con el mensaje de confirmación si usted está usando gerrit.Por favor, Guardar tus cambios antes de seguir próximo alternativas:

  1. Utilizar hard reset a la anterior cometer y, a continuación, a comprometernos este cambio.
  2. Usted también puede guardar el cambio, reajuste y comprometernos.

Hice accidentalmente eliminado el alijo en GitUP de la aplicación.Basta con pulsar Ctrl+Z para deshacer de ella.

Tal vez ayuda a alguien ;)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top