web-dev-qa-db-fra.com

Comment récupérer des modifications non gérées cachées

J'ai eu quelques changements non engagés dans ma branche de développement et je les ai cachés en utilisant git stash, mais certains changements étaient très importants parmi ceux qui étaient cachés. Y a-t-il un moyen de récupérer ces changements?

En outre, j'ai apporté quelques modifications par-dessus les fichiers de code cachés depuis.

Existe-t-il une chance que je récupère les modifications stockées dans une nouvelle branche si possible?

572
Aswathy P Krishnan

La réponse facile à la question facile est _git stash apply_

Il suffit de vérifier la branche sur laquelle vous souhaitez que vos modifications soient apportées, puis _git stash apply_. Puis utilisez _git diff_ pour voir le résultat.

Une fois que vous avez terminé vos modifications - la apply a bonne apparence et vous êtes certain de ne plus avoir besoin de la cachette —then utilisez _git stash drop_ pour vous en débarrasser. de cela.

Je suggère toujours d'utiliser _git stash apply_ plutôt que _git stash pop_. La différence est que apply laisse la réserve pour une nouvelle tentative facile de la apply, ou pour la regarder, etc. Si pop peut extraire la cachette, elle sera immédiatement aussi drop et si vous réalisez soudainement que vous voulez l'extraire ailleurs (dans une branche différente), ou avec _--index_, ou quelque chose du genre, ce n'est pas si facile. Si vous apply, vous allez choisir quand drop.

C'est tout à fait mineur d'une manière ou d'une autre, cependant, et pour un débutant, ce devrait être à peu près le même. (Et vous pouvez sauter tout le reste!)


Et si vous faites des choses plus avancées ou plus compliquées?

Il y a au moins trois ou quatre différentes "manières d'utiliser Git Stash", pour ainsi dire. Ce qui précède est pour "voie 1", le "moyen facile":

  1. Vous avez commencé avec une branche vierge, travailliez sur des modifications et vous vous êtes rendu compte que vous les appliquiez dans la mauvaise branche. Vous voulez juste prendre les modifications que vous avez maintenant et les "déplacer" dans une autre branche.

    C'est le cas facile, décrit ci-dessus. Exécutez _git stash save_ (ou en clair _git stash_, même chose). Découvrez l’autre branche et utilisez _git stash apply_. Cela amène git à fusionner dans vos modifications précédentes, en utilisant le mécanisme de fusion plutôt puissant de git. Inspectez soigneusement les résultats (avec _git diff_) pour voir si vous les aimez et, le cas échéant, utilisez _git stash drop_ pour déposer la réserve. Vous avez terminé!

  2. Vous avez commencé des changements et les avez cachés. Ensuite, vous avez changé de branche et commencé d’autres changements, en oubliant que vous aviez les cachés.

    Maintenant, vous voulez garder, ou même vous déplacer, ceux-ci changent, et ​​appliquent également votre stock.

    En fait, vous pouvez à nouveau _git stash save_, car _git stash_ effectue une "pile" de modifications. Si vous faites cela, vous avez deux cachettes, une juste appelée stash— mais vous pouvez aussi écrire _stash@{0}_— et une épelée _stash@{1}_. Utilisez _git stash list_ (à tout moment) pour les voir tous. Le plus récent est toujours le plus petit numéro. Lorsque vous _git stash drop_, le plus récent est supprimé et celui qui était _stash@{1}_ se place en haut de la pile. Si vous en avez encore plus, celui qui était _stash@{2}_ devient _stash@{1}_, et ainsi de suite.

    Vous pouvez apply puis drop une réserve spécifique également: _git stash apply stash@{2}_, etc. Si vous supprimez une réserve spécifique, seuls les numéros les plus élevés sont numérotés. Là encore, celui sans numéro est également _stash@{0}_.

    Si vous accumulez beaucoup de cachettes, cela peut devenir assez compliqué (la cachette que je voulais _stash@{7}_ ou _stash@{4}_? Attendez, j'en ai poussé une autre, maintenant elles sont 8 et 5?) . Personnellement, je préfère transférer ces modifications dans une nouvelle succursale, car les succursales ont des noms et _cleanup-attempt-in-December_ signifie beaucoup plus pour moi que _stash@{12}_. (La commande _git stash_ prend un message de sauvegarde facultatif, et ceux-ci peuvent aider, mais d’une manière ou d’une autre, toutes mes caches finissent simplement appelées _WIP on branch_.)

  3. (Extra-avancé) Vous avez utilisé _git stash save -p_, ou avec précaution _git add_- ed et/ou _git rm_- bits spécifiques de votre code avant d'exécuter _git stash save_. Vous aviez une version dans la zone d'index/stockage intermédiaire et une autre version (différente) dans l'arborescence de travail. Vous voulez préserver tout cela. Alors maintenant, vous utilisez _git stash apply --index_, et cela échoue parfois avec:

    _Conflicts in index.  Try without --index.
    _
  4. Vous utilisez _git stash save --keep-index_ afin de tester "ce qui sera commis". Celui-ci dépasse le cadre de cette réponse; voir cette autre réponse StackOverflow à la place.

Pour les cas compliqués, je recommande de commencer par un répertoire de travail "propre", en validant les modifications que vous avez maintenant (sur une nouvelle branche si vous le souhaitez). De cette façon, le "quelque part" que vous les appliquez n'a rien d'autre, et vous allez simplement essayer les modifications cachées:

_git status               # see if there's anything you need to commit
                         # uh oh, there is - let's put it on a new temp branch
git checkout -b temp     # create new temp branch to save stuff
git add ...              # add (and/or remove) stuff as needed
git commit               # save first set of changes
_

Maintenant, vous êtes sur un point de départ "propre". Ou peut-être que ça ressemble plus à ça:

_git status               # see if there's anything you need to commit
                         # status says "nothing to commit"
git checkout -b temp     # optional: create new branch for "apply"
git stash apply          # apply stashed changes; see below about --index
_

La principale chose à retenir est que le "stash" est ​​un commit, c'est juste un commit légèrement "drôle/étrange" qui n'est pas "sur une branche". L'opération apply examine ce que le commit a changé et essaie de le répéter où que vous soyez maintenant. La cachette sera toujours là (apply la conservera), afin que vous puissiez la regarder de plus près, ou décider que ce n'était pas le bon endroit pour apply et essayer à nouveau différemment, ou peu importe.


Chaque fois que vous avez une réserve, vous pouvez utiliser _git stash show -p_ pour afficher une version simplifiée de son contenu. (Cette version simplifiée ne concerne que les modifications de "l'arbre de travail final", not ​​l'index sauvegardé change que _--index_ restaure séparément.) La commande _git stash apply_, sans _--index_, essaie juste de faire ces même modifications dans votre répertoire de travail maintenant.

Cela est vrai même si vous avez déjà des modifications. La commande apply est heureuse d'appliquer une réserve à un répertoire de travail modifié (ou du moins d'essayer de l'appliquer). Vous pouvez, par exemple, faire ceci:

_git stash apply stash      # apply top of stash stack
git stash apply stash@{1}  # and mix in next stash stack entry too
_

Vous pouvez choisir l'ordre "appliquer" ici, en sélectionnant des masques particuliers à appliquer dans une séquence particulière. Notez cependant que chaque fois que vous effectuez une "fusion git", et comme le signale la documentation relative à la fusion:

Il est déconseillé de lancer git merge avec des modifications non triviales non validées: cela peut vous laisser dans un état difficile à résoudre en cas de conflit.

Si vous démarrez avec un répertoire vide et que vous effectuez plusieurs opérations _git apply_, il est facile de revenir en arrière: utilisez _git reset --hard_ pour Revenez à l'état de nettoyage et modifiez vos opérations apply. (C'est pourquoi je recommande de commencer par un répertoire de travail propre, pour ces cas compliqués.)


Qu'en est-il du pire cas possible?

Supposons que vous faites beaucoup de choses avancées avec Git, que vous avez créé une cachette et que vous souhaitiez _git stash apply --index_, mais il n'est plus possible d'appliquer la cachette enregistrée avec _--index_, car la branche a divergé trop depuis le temps que vous l'avez enregistré.

C’est à cela que sert _git stash branch_.

Si vous:

  1. vérifier le exact commit ​​vous étiez sur lorsque vous avez fait l'original stash, puis
  2. créer une nouvelle branche et enfin
  3. _git stash apply --index_

la tentative de recréer les modifications définitivement va travailler. C'est ce que _git stash branch newbranch_ fait. (Et puis il lâche la réserve car elle a été appliquée avec succès.)


Quelques derniers mots sur _--index_ (qu'est-ce que c'est que ça?)

Ce que le _--index_ fait est simple à expliquer, mais un peu compliqué en interne:

  • Lorsque vous avez des modifications, vous devez _git add_ (ou les "mettre en scène") avant commiting.
  • Ainsi, lorsque vous avez exécuté _git stash_, vous pourriez avez édité les deux fichiers foo et zorg, mais n’en avez mis en scène qu’un seul.
  • Ainsi, lorsque vous demandez de récupérer votre cachette, cela pourrait être agréable si elle _git add_ est la chose added et fait pas _git add_ les choses non ajoutées. C'est-à-dire que si vous added foo mais pas zorg avant de faire la stash, il serait peut-être agréable d'avoir exactement la même configuration. Ce qui a été mis en scène devrait être à nouveau mis en scène; ce qui a été modifié mais non mis en scène doit à nouveau être modifié mais pas mis en scène.

L'indicateur _--index_ sur apply essaie de configurer les choses de cette façon. Si votre arbre de travail est propre, cela ne fonctionne généralement que. Si votre arbre de travail a déjà des éléments added, vous pouvez voir comment il pourrait y avoir des problèmes ici. Si vous laissez de côté _--index_, l'opération apply ne tente pas de conserver la totalité de la configuration préparée/non stockée. Au lieu de cela, il invoque simplement la machine de fusion de git, en utilisant le commit de l'arbre de travail dans le "sac caché" . Si vous ne vous souciez pas de la conservation par étapes ou par étapes, laisser _--index_ le rendre beaucoup plus facile pour que _git stash apply_ fasse son travail.

958
torek
git stash pop

va tout remettre en place

comme suggéré dans les commentaires, vous pouvez utiliser git stash branch newbranch pour appliquer le stash à une nouvelle branche, ce qui revient au même que de lancer:

git checkout -b newbranch
git stash pop
46
Stefano Falasca

Pour simplifier les choses, vous avez deux options pour réappliquer votre réserve:

  1. git stash pop - Restaure à l'état enregistré, mais supprime le stash du stockage temporaire.
  2. git stash apply - Restaure à l'état enregistré et laisse la liste de masquage pour une réutilisation ultérieure possible.

Vous pouvez lire plus en détail sur git stash dans cet article.

15
Nesha Zoric

Pour vérifier votre contenu stash: -

liste cachée git

appliquer un n ° de cachette particulier de la liste de cachette: -

git stash applique stash @ {2}

ou pour appliquer seulement la première cachette: -

git Stash Pop