Question

J'utilise fréquemment git stash et git stash pop pour enregistrer et restaurer les modifications dans mon arbre de travail. Hier, j'ai eu quelques changements dans mon arbre de travail que j'avais cachés et sautés, puis j'ai apporté d'autres modifications à mon arbre de travail. J'aimerais revenir en arrière et passer en revue les modifications cachées d'hier, mais <=> semble supprimer toutes les références au commit associé.

Je sais que si j'utilise <=>, alors .git / refs / stash contient la référence du commit utilisé pour créer le stash. Et .git / logs / refs / stash contient l'intégralité de la réserve. Mais ces références ont disparu après <=>. Je sais que le commit est toujours dans mon référentiel quelque part, mais je ne sais pas ce que c'était.

Existe-t-il un moyen simple de récupérer la référence de validation de la cachette d'hier?

Notez que cela n’est pas critique pour moi aujourd’hui, car j’ai des sauvegardes quotidiennes et que je peux revenir à l’arborescence de travail d’hier pour obtenir mes modifications. Je demande parce qu'il doit y avoir un moyen plus facile!

Était-ce utile?

La solution

Une fois que vous connaissez le hachage de la validation que vous avez supprimée, vous pouvez l'appliquer en tant que cachette:

git stash apply $stash_hash

Vous pouvez également créer une branche distincte avec

.
git branch recovered $stash_hash

Après cela, vous pouvez faire ce que vous voulez avec tous les outils habituels. Lorsque vous avez & # 8217; terminé, supprimez simplement la branche.

Recherche du hachage

Si vous venez juste de le faire apparaître et que le terminal est toujours ouvert, vous 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, Unix ou Git Bash pour Windows:

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

... ou en utilisant Powershell pour Windows:

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

Cela vous montrera tous les commits aux extrémités de votre graphique de validation qui ne sont plus référencés depuis aucune branche ou balise & # 8211; chaque commit perdu, y compris chaque commit caché que vous avez créé & # 8217, sera quelque part dans ce graphique.

Le moyen le plus simple de trouver la validation que vous voulez utiliser est probablement de transmettre cette liste à gitk:

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

... ou consultez la réponse d'emragins si vous utilisez Powershell pour Windows.

Ceci lancera un navigateur de référentiel affichant chaque validation dans le référentiel , qu'elle soit accessible ou non.

Vous pouvez remplacer git log --graph --oneline --decorate ici par quelque chose comme git stash si vous préférez un joli graphique sur la console plutôt qu'une application graphique distincte.

Pour repérer les validations de masquage, recherchez les messages de validation de ce formulaire:

& nbsp; & nbsp; & nbsp; & nbsp; WIP sur une branche : commithash Un ancien message de validation

Remarque : le message de validation ne se présentera que sous cette forme (commençant par " WIP sur ") si vous n'avez pas fourni de message lorsque vous avez fait <=> .

Autres conseils

Si vous n'avez pas fermé le terminal, regardez simplement le résultat de git stash pop et vous aurez l'ID d'objet de la cachette supprimée. Cela 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 réserve, lancez simplement git branch tmp 2cae03e et vous l'obtiendrez sous forme de branche. Pour convertir cela en une réserve, exécutez:

git stash apply tmp
git stash

L’avoir comme branche vous permet également de la manipuler librement; par exemple, pour le sélectionner ou le fusionner.

Je voulais juste mentionner cet ajout à la solution acceptée. Ce n’était pas évident pour moi la première fois que j’ai essayé cette méthode (peut-être aurait-elle dû l'être), mais pour appliquer la valeur cachée à partir de la valeur de hachage, utilisez simplement & "; Git stash apply &"; / p>

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

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

Pour obtenir la liste des caches encore présentes dans votre référentiel, mais inaccessibles:

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

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

La commande est grepping pour " WIP " car le message de validation par défaut pour une réserve est de la forme WIP on mybranch: [previous-commit-hash] Message of the previous commit.

Je viens de construire une commande qui m'a aidé à retrouver mon commit perdu Stash:

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

Ceci répertorie tous les objets de l’arborescence .git / objects, localise ceux qui sont de type commit, puis affiche un résumé de chacun d’eux. À partir de là, il ne restait plus qu'à regarder à travers les commandes pour trouver un & WIP sur le travail approprié: 6a9bb2 & "; (& "travail &"; est ma branche, 619bb2 est un commit récent).

Je remarque que si j'utilise & "; git stash apply &"; au lieu de & "; git stash pop &"; Je n'aurais pas ce problème et si j'utilise & "; Git stash save message &"; alors le commit aurait peut-être été 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

git fsck --unreachable | grep commit devrait afficher sha1, bien que la liste renvoyée puisse être assez longue. git show <sha1> montrera si c'est le commit que vous voulez.

git cherry-pick -m 1 <sha1> fusionnera la validation sur la branche actuelle.

Si vous souhaitez restaurer une réserve perdue, vous devez d'abord trouver la valeur de hachage de celle-ci.

Comme Aristote Pagaltzis l’a suggéré, un git fsck devrait vous aider.

Personnellement, j'utilise mon log-all alias qui me montre chaque commit (commets récupérables) pour avoir une meilleure vue d'ensemble de la situation:

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

Vous pouvez effectuer une recherche encore plus rapide si vous ne recherchez que " WIP sur " messages.

Une fois que vous connaissez votre sha1, il vous suffit de modifier le statut de votre cachette pour y ajouter l'ancien cachette:

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' $1) refs/stash $1

Équivalent Windows PowerShell à l'aide de gitk:

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

Il existe probablement un moyen plus efficace de le faire dans un seul tuyau, mais cela fait l'affaire.

J'ai bien aimé l'approche d'Aristote, mais n'aimais pas utiliser GITK ... car je suis habitué à utiliser GIT à partir de la ligne de commande.

Au lieu de cela, j'ai pris les commits en suspens et ai généré le code dans un fichier DIFF pour examen dans mon éditeur de code.

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

Vous pouvez maintenant charger le fichier diff / txt obtenu (dans votre dossier de départ) dans votre éditeur de texte et voir le code actuel et le SHA résultant.

Ensuite, utilisez simplement

git stash apply ad38abbf76e26c803b27a6079348192d32f52219

Sous OSX avec git v2.6.4, je viens d’exécuter accidentellement git stash drop, puis je l’ai trouvé en suivant les étapes ci-dessous

Si vous connaissez le nom de la réserve, 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 manuellement à l'aide de:

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

Puis, lorsque vous trouvez l'ID de validation, appuyez simplement sur la cachette git apply {id-de-validation}

J'espère que cela aide rapidement quelqu'un

Pourquoi les gens posent-ils cette question? Parce qu’ils ne connaissent pas encore et ne comprennent pas le reflog.

La plupart des réponses à cette question donnent de longues commandes avec des options dont presque personne ne se souviendra. Alors, les gens entrent dans cette question et copient-collent tout ce dont ils pensent avoir besoin et l’oublient presque immédiatement après.

Je conseillerais à tous ceux qui ont cette question de vérifier le reflog (git reflog), pas beaucoup plus que cela. Une fois que vous voyez cette liste de tous les commits, il existe une centaine de façons de déterminer le commet que vous recherchez et de le sélectionner ou de créer une branche à partir de celle-ci. Au cours de ce processus, vous en apprendrez davantage sur le processus de refonte et sur les options utiles des différentes commandes git de base.

Vous pouvez répertorier tous les commits inaccessibles en écrivant cette commande dans le terminal -

git fsck --unreachable

Vérifier le hachage de validation inaccessible -

git show hash

Enfin, appliquez si vous trouvez l'élément caché -

git stash apply hash

Je souhaite ajouter à la solution acceptée un autre bon moyen de passer en revue tous les changements, lorsque vous ne disposez pas de gitk ou d'aucun X pour la sortie.

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

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

Ensuite, vous obtenez toutes les différences pour ces hachages affichées les unes après les autres. Appuyez sur 'q' pour passer au diff suivant.

La réponse acceptée par Aristote indiquera tous les commits accessibles, y compris les commits non stash. Pour filtrer le bruit:

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

Ceci n'inclut que les commits qui ont exactement 3 commits parents (une cachette aura), et dont le message inclut & "WIP on &";

.

N'oubliez pas que si vous sauvegardez votre réserve avec un message (par exemple, git stash save "My newly created stash"), cela remplacera la valeur par défaut " WIP on ... " message.

Vous pouvez afficher plus d'informations sur chaque commit, par exemple. affichez le message de validation ou transmettez-le à 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

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

  • première exécution: git fsck --unreachable | findstr "commit"
  • copier le résultat dans le bloc-notes
  • trouver remplacer " commit inaccessible " avec 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

  • enregistrez en tant que fichier .bat et exécutez-le
  • le script ouvrira un tas de fenêtres de commande, montrant chaque commit
  • si vous avez trouvé celui que vous cherchez, lancez: git stash apply (your hash)

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

Ce que je suis venu chercher ici, c'est comment récupérer le cachette, peu importe ce que j'ai vérifié. En particulier, j'avais caché quelque chose, puis extrait une version plus ancienne, puis je l'avais affichée, mais la cachette était inopérante à ce moment-là, de sorte que la cachette a disparu; Je ne pouvais pas simplement faire git stash pour le repousser dans 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.

En rétrospective, j'aurais dû utiliser git stash apply et non git stash pop. Je faisais un bisect et j'avais un petit patch que je voulais appliquer à chaque <=> étape. Maintenant je fais ça:

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

Il a été récupéré en procédant comme suit:

  1. Identifiez le code de hachage de stockage masqué supprimé:

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

  2. Cherry Choisissez la cachette:

    git cherry-pick -m 1 $ stash_hash_code

  3. Résolvez les conflits éventuels en utilisant:

    git mergetool

De plus, vous pourriez avoir des problèmes avec le message de validation si vous utilisez gerrit. Rangez vos modifications avant de suivre les alternatives suivantes:

  1. Utilisez une réinitialisation matérielle à la validation précédente, puis recommencez cette modification.
  2. Vous pouvez également cacher la modification, créer une nouvelle base et recommencer.

J'ai supprimé accidentellement la réserve dans l'application GitUP. Appuyez simplement sur Ctrl + Z pour l'annuler.

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top