Annulation accidentelle de Git Stash Pop

186

J'ai caché quelques modifications locales avant de faire une fusion compliquée, j'ai fait la fusion, puis j'ai bêtement oublié de valider avant de courir git stash pop. Le pop a créé quelques problèmes (mauvais appels de méthode dans une grande base de code) qui s'avèrent difficiles à localiser. J'ai couru git stash show, donc je sais au moins quels fichiers ont été modifiés. Si rien d'autre, je suppose que c'est une leçon pour s'engager davantage.

Ma question: est-il possible d'annuler le stash pop sans annuler également la fusion?

nren
la source
2
Vous n'êtes pas censé y être autorisé git stash popsans vous engager au préalable. Qu'avez-vous fait pour y parvenir?
Chris Jester-Young
Pas sûr d'être honnête (c'était hier). La fusion ne s'est pas validée d'elle-même car il y avait des conflits. J'ai été en quelque sorte capable d'exécuter du stash pop après cela.
nren
1
Je l'ai fait juste en utilisant la version 1.7.9.msysgit.0 de git. J'avais des fichiers non mis en scène et la pop cachée venait de tout fusionner.
PandaWood
J'ai pu courir git stash popaprès avoir organisé les changements (je ne me suis pas engagé cependant) avec la version 2.25.0.windows.1 de git
Artem Hevorhian
Si vous avez indexé vos modifications et les avez perdues au cours de votre exécution stash pop/applyavant d'effectuer une validation, vous pouvez déclencher git fsck --lost-found. Cette commande itérera à travers les blobs pendantes (fichiers réels pour ceux qui ne sont pas familiers avec la terminologie git) qui ont été mis en scène mais qui ne sont validés nulle part (donc pendants), et les placent dans le répertoire .git / lost-found / , où vous pouvez git showles voir si ce sont les fichiers que vous recherchez.
Artem Hevorhian le

Réponses:

69

Essayez d'utiliser Comment récupérer une cachette abandonnée dans Git? pour trouver la cachette que vous avez sauté. Je pense qu'il y a toujours deux commits pour un stash, car il préserve l'index et la copie de travail (si souvent le commit d'index sera vide). Puis- git showles pour voir les différences et les utiliser patch -Rpour les désappliquer.

Ben Jackson
la source
6
Wow cela a fonctionné. J'ai pu trouver les commits stash avec git fsck --no-reflog | awk '/dangling commit/ {print $3}'(à partir du lien), et je viens de trouver manuellement le problème à partir de ce diff. Merci!
nren
1
le fsck produit une liste énorme. C'est fastidieux de montrer chaque SHA1 là-bas. Comment est-ce que tu fais ça ?
meson10
5
@ meson10: Malheureusement, les stashs sont conservés dans un reflog, ce qui serait le moyen le plus évident (s'il s'agissait d'une vraie branche) de regarder l'historique des stashes sautés. Permettez-moi également de suggérer qu'un vote négatif + une demande d'aide n'est pas la meilleure stratégie.
Ben Jackson
2
Il m'a fallu un peu de mal pour faire les choses correctement. Voici le résultat de mon travail git diff -p ${STACH_SHA1}~1 ${STASH_SHA1} | patch -R -p1:; J'ai essayé avec git showcomme suggéré mais sa sortie n'était pas bonne pour le patch; j'ai également dû fournir l' -p1option de patcher afin de supprimer l' élément a/..et b/..qui git diffplace les fichiers devant les fichiers, sinon cela ne résoudrait pas les chemins à partir de la racine du référentiel. SUGGESTION: soyez prudent et commettez le désordre dans une branche séparée avant de jouer avec le patch.
basilikode le
@BenJackson Dans votre réponse "toujours" signifie les deux stash popet stash pushdéclenchera un commit qui enregistrerait les modifications dans l'index et le répertoire de travail, non?
Artem Hevorhian le
36

De git stash --help

Recovering stashes that were cleared/dropped erroneously
   If you mistakenly drop or clear stashes, they cannot be recovered through the normal safety mechanisms. However, you can try the
   following incantation to get a list of stashes that are still in your repository, but not reachable any more:

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

Cela m'a aidé mieux que la réponse acceptée avec le même scénario.

Kachar
la source
13
Notez que de nombreuses solutions qui impliquent la recherche de "WIP" reposent sur les messages de cache par défaut. Si vous donnez à vos stashes des messages explicites, ils peuvent ne pas contenir WIP.
Ben Jackson
Merci. J'ai ajouté l'option --oneline à la commande log pour améliorer la lisibilité.
basslo
Cela vous aide uniquement à trouver le SHA du commit stash. Mais s'il est intégré au commentaire @basilikode de la réponse acceptée (git diff SHA ~ 1 SHA | patch -R), cela fonctionne très bien. Je recommande d'utiliser le chemin --dry-run d'abord pour vérifier.
Jarek C
3

Si votre fusion n'était pas trop compliquée, une autre option serait de:

  1. Remettez toutes les modifications, y compris les modifications de fusion, dans stash en utilisant "git stash"
  2. Exécutez à nouveau la fusion et validez vos modifications (sans les modifications de la réserve supprimée)
  3. Exécutez un "git stash pop" qui devrait ignorer toutes les modifications de votre fusion précédente puisque les fichiers sont maintenant identiques.

Après cela, il ne vous reste plus que les modifications de la réserve que vous avez déposée trop tôt.

Markus
la source