¿Cómo recupero un alijo caído en Git?

Resuelto Greg Hewgill asked hace 16 años • 25 respuestas

Utilizo frecuentemente git stashy git stash poppara guardar y restaurar cambios en mi árbol de trabajo. Ayer tuve algunos cambios en mi árbol de trabajo que había escondido y sacado, y luego hice más cambios en mi árbol de trabajo. Me gustaría volver atrás y revisar los cambios escondidos de ayer, pero git stash popparece que se eliminan todas las referencias a la confirmación asociada.

Sé que si lo uso git stash, .git/refs/stash contiene la referencia de la confirmación utilizada para crear el alijo. Y .git/logs/refs/stash contiene todo el alijo. Pero esas referencias desaparecieron después git stash pop. Sé que la confirmación todavía está en algún lugar de mi repositorio, pero no sé qué fue.

¿Existe una manera fácil de recuperar la referencia de confirmación del alijo de ayer?

Greg Hewgill avatar Sep 18 '08 08:09 Greg Hewgill
Aceptado

Una vez que conozca el hash del compromiso de alijo que soltó, puede aplicarlo como un alijo:

git stash apply $stash_hash

O puede crear una rama separada para ello con

git branch recovered $stash_hash

Después de eso, podrás hacer lo que quieras con todas las herramientas normales. Cuando hayas terminado, simplemente quita la rama.

Encontrar el hash

Si acaba de abrirlo y el terminal aún está abierto, aún tendrá el valor hash impreso en git stash popla pantalla (gracias, Dolda).

De lo contrario, puedes encontrarlo usando esto para Linux, Unix o Git Bash para Windows:

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

...o usando PowerShell para Windows:

git fsck --no-reflog | select-string 'dangling commit' | foreach { $_.ToString().Split(" ")[2] }

Esto le mostrará todas las confirmaciones en las puntas de su gráfico de confirmaciones a las que ya no se hace referencia desde ninguna rama o etiqueta; cada confirmación perdida, incluidas todas las confirmaciones ocultas que haya creado, estará en algún lugar de ese gráfico.

La forma más sencilla de encontrar la confirmación de alijo que desea es probablemente pasar esa lista a gitk:

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

...o vea la respuesta de emragins si usa PowerShell para Windows.

Esto iniciará un navegador de repositorio que le mostrará cada confirmación en el repositorio , independientemente de si es accesible o no.

Puede reemplazarlo gitkcon algo como git log --graph --oneline --decoratesi prefiere un buen gráfico en la consola en lugar de una aplicación GUI separada.

Para detectar confirmaciones de alijo, busque mensajes de confirmación de este formulario:

        WIP en alguna rama : commithash Algún mensaje de confirmación antiguo

Nota : El mensaje de confirmación solo tendrá este formato (comenzando con "WIP activado") si no proporcionó un mensaje cuando lo hizo git stash.

Aristotle Pagaltzis avatar Sep 18 '2008 11:09 Aristotle Pagaltzis

Si no cerró la terminal, simplemente mire el resultado git stash popy tendrá el ID del objeto del alijo eliminado. Normalmente se ve así:

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

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

Para recuperar ese alijo, simplemente ejecuta git branch tmp 2cae03ey lo obtendrás como una rama. Para convertir esto en un alijo, ejecute:

git stash apply tmp
git stash

Tenerlo como rama también te permite manipularlo libremente; por ejemplo, para seleccionarlo o fusionarlo.

Dolda2000 avatar Oct 21 '2011 03:10 Dolda2000

Solo quería mencionar esta adición a la solución aceptada. No fue inmediatamente obvio para mí la primera vez que probé este método (tal vez debería haberlo sido), pero para aplicar el alijo del valor hash, simplemente use "git stash apply":

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

Cuando era nuevo en git, esto no me quedaba claro y estaba probando diferentes combinaciones de "git show", "git apply", "patch", etc.

Wade avatar Mar 03 '2009 20:03 Wade

Para obtener la lista de alijos que todavía están en su repositorio, pero que ya no son accesibles:

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

Si le diste un título a tu alijo, reemplaza "WIP" al -grep=WIPfinal del comando con una parte de tu mensaje, por ejemplo -grep=Tesselation.

El comando busca "WIP" porque el mensaje de confirmación predeterminado para un alijo tiene el formatoWIP on mybranch: [previous-commit-hash] Message of the previous commit.

Cuando haya encontrado el compromiso, aplíquelo congit stash apply <commit_hash>

Senthil A Kumar avatar May 04 '2011 06:05 Senthil A Kumar

Equivalente de Windows PowerShell usando gitk:

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

Probablemente exista una forma más eficiente de hacer esto en una tubería, pero funciona.

emragins avatar Jan 07 '2016 23:01 emragins