Comment récupérer une cachette déposée dans Git?

j'utilise fréquemment git stash et git stash pop pour sauvegarder et restaurer les modifications dans mon arbre de travail. Hier, j'ai eu quelques changements dans mon arbre de travail que j'avais planqué et fait sauter, et puis j'ai fait plus de changements à mon arbre de travail. J'aimerais revenir en arrière et passer en revue les modifications cachées d'hier, mais git stash pop semble supprimer toutes les références à la propagation associée.

je sais que si j'utilise git stash puis .git/refs / stash contient le référence de la validation utilisé pour créer la cachette. Et .git/logs/refs / stash contient la totalité de la stash. Mais ces références sont allées après git stash pop . Je sais que la livraison est toujours dans mon référentiel quelque part, mais je ne sais pas ce que c'était.

y a-t-il un moyen facile de récupérer la référence de Stash commit d'hier?

Notez que ce n'est pas important pour moi aujourd'hui parce que j'ai des sauvegardes quotidiennes et peut revenir à hier je travaille sur l'arbre pour avoir mes changements. Je demande parce qu'il doit y avoir un moyen plus facile!

1355
demandé sur Randall 2008-09-18 05:59:06

19 réponses

si vous venez juste de l'ouvrir et que le terminal est toujours ouvert, vous aurez toujours la valeur de hachage imprimée par git stash pop à l'écran (Merci, Dolda).

sinon, vous pouvez le trouver en utilisant ceci Pour Linux et Unix:

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

et pour Windows:

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

cela vous montrera toutes les commits à l'extrémité de votre graphique de commit qui ne sont plus référencées à partir de branche ou étiquette-chaque commit perdu, y compris chaque Stash commit que vous avez créé, sera quelque part dans ce graphique.

la façon la plus facile de trouver le Stash commit que vous voulez est probablement de passer cette liste à gitk :

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

cela lancera un navigateur de dépôt vous montrant chaque commit dans le dépôt jamais , qu'il soit accessible ou non.

vous pouvez remplacez gitk par quelque chose comme git log --graph --oneline --decorate si vous préférez un graphique agréable sur la console plutôt qu'une interface graphique séparée.

pour repérer les commits de Stash, recherchez les messages de commit de ce formulaire:

WIP on somebranch : commihash Some old commit message

Note : le message de propagation ne sera que sous cette forme (en commençant par " WIP sur") si vous n'avez pas fourni un message lorsque vous avez fait git stash .

une fois que vous connaissez le hachage du commit que vous voulez, vous pouvez l'appliquer comme une cachette:

git stash apply $stash_hash

ou vous pouvez utiliser le menu contextuel dans gitk pour créer des branches pour toutes les propagations inaccessibles qui vous intéressent. Après cela, vous pouvez faire ce que vous voulez avec eux, avec tous les outils. Quand tu auras fini, souffle encore ces branches.

2195
répondu Aristotle Pagaltzis 2017-05-23 12:10:54

si vous n'avez pas fermé le terminal, regardez simplement la sortie de git stash pop et vous aurez L'ID de l'objet de la cachette larguée. Il ressemble normalement à ceci:

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

(notez que git stash drop produit également la même ligne.)

pour récupérer cette cachette, il suffit de lancer git branch tmp 2cae03e , et vous l'obtiendrez en tant que branche. Convertir cette cachette, exécutez:

git stash apply tmp
git stash

Ayant comme une branche vous permet également de manipuler librement; par exemple, pour choisir ou de le fusionner.

617
répondu Dolda2000 2012-02-22 23:45:33

voulait juste mentionner cet ajout à la solution acceptée. Ce n'était pas tout de suite évident pour moi la première fois que j'ai essayé cette méthode (peut-être qu'elle aurait dû l'être), mais pour appliquer la cachette de la valeur de hachage, il suffit d'utiliser " git stash appliquer ":

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

Quand j'étais nouveau, git, ce n'était pas clair pour moi, et j'ai essayé différentes combinaisons de "git show", "git apply", "patch", etc.

238
répondu Wade 2009-03-03 20:28:51

je viens de construire une commande qui m'a aidé à retrouver ma réserve perdue:

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

cette liste répertorie tous les objets dans le .git/objects arbre, localise ceux qui sont de type valider, puis affiche un résumé de chacun d'eux. À partir de ce point, il s'agissait simplement de regarder à travers les commits pour trouver une "WIP sur le travail: 6a9bb2" ("le travail" est ma branche, 619bb2 est un commit récent).

je note que si j'utilise "git stash s'applique" au lieu de "git stash pop" Je n'aurais pas ce problème, et si j'utilise "git stash save message " alors la propagation aurait pu être plus facile à trouver.

mise à jour: avec L'idée de Nathan, cela devient plus court:

for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less
69
répondu Greg Hewgill 2008-09-18 02:10:13

pour obtenir la liste des caches qui sont encore dans votre dépôt, mais qui ne sont plus accessibles:

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

si vous avez donné un titre à votre cachette, remplacez "WIP" dans -grep=WIP à la fin de la commande par une partie de votre message, par exemple -grep=Tesselation .

la commande grepping for "WIP" parce que le message de propagation par défaut pour une cachette est sous la forme WIP on mybranch: [previous-commit-hash] Message of the previous commit.

64
répondu Senthil A Kumar 2017-09-19 12:01:28

git fsck --unreachable | grep commit devrait afficher le sha1, bien que la liste qu'il renvoie puisse être assez large. git show <sha1> montrera si c'est le commit que vous voulez.

git cherry-pick -m 1 <sha1> va fusionner le commit sur la branche courante.

37
répondu Nathan Jones 2008-09-18 02:14:27

si vous voulez reconstituer une réserve perdue, vous devez d'abord trouver la réserve perdue.

comme Aristotle Pagaltzis a suggéré un git fsck devrait vous aider.

personnellement j'utilise mon alias log-all qui me montre chaque commit (récupérable commits) pour avoir une meilleure vue de la situation:

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

vous pouvez faire une recherche encore plus rapide si vous cherchez seulement des messages" WIP on".

une fois que vous connaissez votre sha1, il vous suffit de changer votre carnet de stock pour ajouter le vieux stash:

git update-ref refs/stash ed6721d

vous préférerez probablement avoir un message associé donc un -m

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

et vous voudrez même l'utiliser comme alias:

restash = !git update-ref -m $(git log -1 --pretty=format:'%s' ) refs/stash 
23
répondu Colin Hebert 2018-01-09 22:18:52

j'ai aimé L'approche D'Aristote, mais je n'ai pas aimé utiliser GITK... comme j'ai l'habitude d'utiliser GIT depuis la ligne de commande.

à la place, j'ai pris les propagations pendantes et sorti le code dans un fichier DIFF pour révision dans mon éditeur de code.

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

maintenant, vous pouvez charger le fichier diff/txt résultant (its dans votre dossier personnel) dans votre éditeur txt et voir le code réel et SHA résultant.

alors il suffit d'utiliser

git stash apply ad38abbf76e26c803b27a6079348192d32f52219
15
répondu Shaheen Ghiassy 2013-01-07 20:17:34

en OSX avec git v2.6.4, je viens de lancer git stash drop accidentellement, puis je l'ai trouvé en allant creux en dessous des étapes

si vous connaissez le nom de la cachette, alors utilisez:

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

sinon vous trouverez L'ID du résultat par manuellement avec:

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

puis quand vous trouvez le commit-id juste frapper la git stash appliquer {commit-id}

J'espère que aide quelqu'un rapidement

12
répondu Can Tecim 2016-11-01 09:57:53

Windows PowerShell équivalent de l'aide gitk:

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

il y a probablement un moyen plus efficace de le faire dans un seul tuyau, mais cela fait le travail.

11
répondu emragins 2016-01-07 23:22:05

je veux ajouter à la solution acceptée une autre bonne façon de passer par toutes les modifications, quand vous n'avez pas gitk disponible ou pas de X pour la sortie.

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

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

ensuite, vous obtenez tous les diffs pour ces hashs affichés l'un après l'autre. Appuyez sur ' q ' pour obtenir la prochaine diff.

10
répondu Phil 2013-01-04 12:32:19

pourquoi les gens posent-ils cette question? Parce qu'ils ne savent pas encore ou ne comprennent pas encore le refrog.

la plupart des réponses à cette question donnent de longues commandes avec des options dont personne ne se souviendra. Donc les gens viennent dans cette question et copient collent tout ce dont ils pensent qu'ils ont besoin et l'oublient presque immédiatement après.

je conseillerais à tout le monde avec cette question de simplement vérifier le refrog (git refrog), pas beaucoup plus que cela. Une fois que vous voyez que liste de tous les commits il y a une centaine de façons de trouver ce que vous cherchez et de le sélectionner ou d'en créer une branche. Dans le processus, vous aurez appris au sujet du reclog et des options utiles à diverses commandes git de base.

10
répondu RobbyD 2016-05-26 10:38:18

Les accepté de répondre par Aristote montrera tous accessibles s'engage, y compris les non-dissimulée-comme valide. Pour filtrer le bruit:

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

ceci inclura seulement les commits qui ont exactement 3 commits parent (ce qu'une stash aura), et dont le message inclut"WIP on".

gardez à l'esprit que si vous avez sauvegardé votre stock avec un message (par exemple git stash save "My newly created stash" ), cela va annuler la valeur par défaut "WIP on..." message.

Vous pouvez afficher plus d'informations sur chaque commit, par exemple afficher le message de commit, ou le passer à git stash show :

git fsck --no-reflog | \
awk '/dangling commit/ {print }' | \
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
9
répondu Brad Feehan 2016-05-17 04:33:50

Je ne pouvais obtenir aucune des réponses pour travailler sur Windows dans une fenêtre de commande simple (Windows 7 dans mon cas). awk , grep et Select-string n'étaient pas reconnus comme des commandes. J'ai donc essayé une approche différente:

  • première manche: git fsck --unreachable | findstr "commit"
  • copiez la sortie sur Bloc-notes
  • remplacer "unreachable commit" par start cmd /k git show

ressemblera à quelque chose comme ceci:

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

  • enregistrer en tant que .batte de fichier et de l'exécuter
  • le script va ouvrir un tas de fenêtres de commande, montrant chaque commit
  • si vous avez trouvé celui que vous cherchez, lancez: git stash apply (your hash)

peut-être pas la meilleure solution, mais a fonctionné pour moi

8
répondu kromakollision 2017-02-28 15:01:39

ce que je suis venu chercher ici, c'est comment récupérer la cachette, peu importe ce que j'ai vérifié. En particulier, j'avais caché quelque chose, puis j'ai vérifié une version plus ancienne, puis je l'ai popé, mais la cachette était un no-op à ce moment-là plus tôt, donc la cachette a disparu; Je ne pouvais pas juste faire git stash pour la repousser sur la pile. Cela a fonctionné pour moi:

$ 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.

rétrospectivement, j'aurais dû utiliser git stash apply et non git stash pop . J'ai été faire un bisect et avait un petit patch que je voulais appliquer à chaque étape bisect . Maintenant je fais ceci:

$ git reset --hard; git bisect good; git stash apply
$ # Run tests
$ git reset --hard; git bisect bad; git stash apply
etc.
4
répondu Ben 2013-11-07 15:13:25

Récupéré en utilisant les étapes suivantes:

  1. identifier le code de hachage de stash supprimé:

    gitk -- $ git( fsck --no-reflog | awk '/balançant s'engager/ {print $3}' )

  2. "151900920 '" écrémer la Cachette:

    git cherry-pick -m 1 $stash_hash_code

  3. Résoudre les Conflits si toute l'aide:

    git mergetool

de plus, vous pourriez avoir des problèmes avec le message de propagation si vous utilisez gerrit. S'il vous plaît, Rangez vos modifications avant de suivre les alternatives suivantes:

  1. utilisez la réinitialisation dure à la propagation précédente, puis réengagez ce changement.
  2. vous pouvez également cacher le changement, rebasé et se réengager.
4
répondu Abhijeet 2016-02-16 11:20:14

vous pouvez lister toutes les propagations inaccessibles en écrivant cette commande dans terminal -

git fsck --unreachable

Case inaccessible commettre de hachage

git show hash

enfin appliquer si vous trouvez l'article caché -

git stash apply hash
4
répondu Vivek Kumar 2018-03-07 11:31:52

un autre cas d'usage courant: vous avez essayé de sauter sur la mauvaise branche et avez eu des conflits?

tout ce que vous voulez est d'annuler le pop mais toujours garder dans la liste de stash afin que vous pouvez pop out sur la branche correcte.

pour le fixer, faire ce qui suit:

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

fait!

0
répondu dorony 2018-02-07 11:41:52

j'ai accidentellement retiré la cachette de L'application GitUP. Il suffit d'appuyer sur Ctrl+Z pour le défaire.

Peut-être que ça aide quelqu'un ;)

0
répondu Nik Kov 2018-07-27 09:52:37