Pourquoi le stash ne peut-il pas être appliqué au répertoire de travail?

96

Je ne peux pas réappliquer le stash au répertoire de travail.

Petite histoire:

J'ai d'abord essayé de pousser quelques modifications validées, mais cela disait: "non, vous ne pouvez pas, tirez d'abord" ... OK alors, je vais extraire des choses de GitHub et ensuite pousser mes modifications. Quand j'ai essayé de tirer, il a dit que j'avais des modifications qui seraient écrasées et que je devais cacher mes modifications. OK, j'ai caché les changements ... j'ai fait l'extraction et j'ai poussé les changements validés. Mais maintenant, je ne peux pas restaurer les modifications non validées sur lesquelles je travaillais.

Voici l'erreur:

MyPath/File.cs already exists, no checkout
Could not restore untracked files from stash

Bien sûr, je ne comprends pas encore tous les concepts de git, ils me déroutent un peu ... peut-être que j'ai fait quelque chose de mal.

Ce serait formidable si quelqu'un pouvait m'aider à résoudre ce problème ... Cela fait plus d'une heure que je cherche sur Google et tout, et je n'ai pas encore trouvé de solution.

L'aide est très appréciée. Merci!

Miguel Angelo
la source

Réponses:

74

Il semble que votre réserve comprenait un fichier non suivi qui a ensuite été ajouté au dépôt. Lorsque vous essayez de le vérifier, git refuse à juste titre car il écraserait un fichier existant.

Pour résoudre le problème, vous pouvez faire quelque chose comme supprimer ce fichier (ce n'est pas grave, il est toujours dans le dépôt), appliquer votre cachette, puis remplacer la version cachée du fichier par la version in-repo, le cas échéant.

Modifier: il est également possible que le fichier n'ait été créé que dans l'arborescence de travail sans avoir été ajouté au dépôt. Dans ce cas, ne supprimez pas simplement le fichier local, mais plutôt:

  1. déplacez-le ailleurs
  2. appliquer la cachette
  3. fusionnez manuellement les deux versions de fichier (arborescence de travail ou déplacée).
blahdiblah
la source
2
Y a-t-il un moyen d'éviter d'avoir à cacher des choses à l'avenir ... Je viens de SVN, et il a tellement hâte ... de mettre à jour, de résoudre les conflits, puis de vous engager. Git ne peut pas être si difficile, que je dois ajouter 2 étapes dans le cycle. Merci encore!
Miguel Angelo
2
@Miguel: Cacher n'est pas un obstacle. C'est un outil supplémentaire fourni par Git qui vous permet d'améliorer votre flux de travail et d'éviter les conflits et les commits impurs. git-scm.com/docs/git-stash
Koraktor
8
Bien que la réponse soit valide, je ne suis vraiment pas sûr que git soit "correct" à ce sujet. Les fichiers sont dans le référentiel, il n'y a donc aucun risque de perte de données. pourquoi ne pas simplement appliquer les changements? Voir cette discussion - git.661346.n2.nabble.com/stash-refuses-to-pop-td7453780.html
studgeek
5
Je pense que cette réponse n'est pas la plus utile. git stashdevrait aider à sauvegarder rapidement les modifications locales. La suppression manuelle d'un ensemble de fichiers pour le restaurer interrompt le flux. L' git stash branchapproche de l'autre réponse sonne mieux, mais reste beaucoup plus manuelle que souhaité.
bentolor le
Cette réponse fonctionnait le mieux pour moi dans la même situation. Après avoir sauté la cachette, je suis passé par une fusion comme je l'aurais attendu depuis le début.
Billy Lazzaro
58

Le moyen le plus sûr et le plus simple serait probablement de ranger à nouveau les choses:

git stash -u             # This will stash everything, including unstaged files
git stash pop stash@{1}  # This will apply your original stash

Ensuite, si vous êtes satisfait du résultat, vous pouvez appeler

git stash drop

pour supprimer votre réserve «sûre».

Koraktor
la source
2
Merci pour cela, m'a sauvé de beaucoup de douleur et de souffrance!
danjarvis
9
stash pop s'appliquera et déposera votre réserve d'origine. Juste pour une utilisation sûre applyau lieu de pop.
Hilbrand Bouwkamp
2
En fait, popc'est une combinaison de applyet drop, mais ne le fera que dropsi le applytravail fonctionne sans conflits. Mais oui, applyc'est généralement plus sûr.
Koraktor
2
Cela suppose qu'il n'y a pas d'autres modifications dans le répertoire de travail que vous souhaitez conserver. Pour cette question particulière, il implique (mais ne le dit pas explicitement) qu'il est dans un état propre, mais je voulais le souligner pour les autres qui viennent ici avec des changements locaux.
studgeek
1
Cela ne résout le problème que si les problèmes conflictuels n'ont pas été commis . Vous obtenez exactement le même message quand ils ont été validés (par exemple avec un checkout propre) et cela ne changera rien ...
Jasper
56

Comme mentionné par @bentolo, vous pouvez supprimer manuellement les fichiers dont il se plaint, changer de branche, puis les rajouter manuellement. Mais je préfère personnellement rester "dans git".

La meilleure façon de procéder est de convertir la réserve en branche. Une fois qu'il s'agit d'une branche, vous pouvez travailler normalement dans git en utilisant les techniques / outils normaux liés aux branches que vous connaissez et aimez. C'est en fait une technique générale utile pour travailler avec des stashes même si vous n'avez pas l'erreur répertoriée. Cela fonctionne bien car un stash est vraiment un commit sous les couvertures (voir PS).

Conversion d'une réserve en branche

Ce qui suit crée une branche basée sur le HEAD lorsque le stash a été créé et applique ensuite le stash (il ne le valide pas).

git stash branch STASHBRANCH

Travailler avec la "branche cachée"

Ce que vous faites ensuite dépend de la relation entre la cachette et où se trouve votre branche cible (que j'appellerai ORIGINALBRANCH).

Option 1 - Rebase stash branch normalement (beaucoup de changements depuis stash)

Si vous avez effectué de nombreux changements dans votre ORIGINALBRANCH, il vaut probablement mieux traiter STASHBRANCH comme n'importe quelle succursale locale. Validez vos modifications dans STASHBRANCH, rebasez-le sur ORIGINALBRANCH, puis passez à ORIGINALBRANCH et rebase / fusionnez les modifications STASHBRANCH dessus. S'il y a des conflits, gérez-les normalement (l'un des avantages de cette approche est que vous pouvez voir et résoudre les conflits).

Option 2 - Réinitialiser la branche d'origine pour qu'elle corresponde à la réserve (changements limités depuis la réserve)

Si vous venez de mettre en cache tout en conservant certaines modifications par étapes, puis que vous les avez validées, et que tout ce que vous voulez faire est d'obtenir les modifications supplémentaires qui n'ont pas été mises en scène lorsque vous avez stocké, vous pouvez effectuer les opérations suivantes. Il reviendra à votre branche et index d'origine sans changer votre copie de travail. Le résultat final sera vos modifications de réserve supplémentaires dans votre copie de travail.

git symbolic-ref HEAD refs/heads/ORIGINALBRANCH
git reset

Contexte

Les stashes sont des commits comme des branches / balises (pas des correctifs)

PS, il est tentant de penser à un stash comme un patch (tout comme il est tentant de penser à un commit comme un patch), mais un stash est en fait un commit contre le HEAD quand il a été créé. Lorsque vous appliquez / pop, vous faites quelque chose de similaire à la sélection dans votre branche actuelle. Gardez à l'esprit que les branches et les balises ne sont en réalité que des références à des commits, donc à bien des égards, les stashes, les branches et les balises ne sont que des façons différentes de pointer vers un commit (et son historique).

Parfois nécessaire même lorsque vous n'avez pas apporté de modifications au répertoire de travail

PPS, Vous pouvez avoir besoin de cette technique après avoir simplement utilisé stash avec --patch et / ou --include-untracked. Même sans modifier les répertoires de travail, ces options peuvent parfois créer une réserve que vous ne pouvez pas simplement réappliquer. Je dois admettre que je ne comprends pas entièrement pourquoi. Voir http://git.661346.n2.nabble.com/stash-refuses-to-pop-td7453780.html pour une discussion.

studgeek
la source
5
Cette réponse doit être marquée comme solution car elle fournit les conseils les plus utiles sur la façon de résoudre le plus efficacement une «réserve verrouillée». Peut-être l'améliorer en mentionnant d'abord la «solution de suppression simple» et la solution de branche comme deuxième option.
bentolor
8
"git stash branch STASHBRANCH" ne semble pas fonctionner si vous êtes confronté à ce scénario (exactement le même message d'erreur se produit avec pop). Vous devrez peut-être faire des réinitialisations de git au préalable.
+1 Je me suis dans un désordre spaghetti avec commits et des changements et stashing etc etc Cela me suis sorti de par POPING la planque à une branche grâce studgeek
RobbZ
Merci pour la clarification sur le fait que les cachettes ne sont pas des correctifs et comment elles sont liées à la HEAD (au moment de la sauvegarde). Cela a du sens. - Donc ... je suppose qu'il y a des cas où il est plus flexible / portable / pratique de créer un patch plutôt qu'une cachette (comme vous l'avez mentionné: lorsque vous avez beaucoup de changements), afin qu'il puisse être appliqué n'importe où (et est juste une question de résolution des conflits). Peut git stash show -p- être y contribue-t-il à faire de la cachette -> * patch *.
Kamafeather
39

La solution: vous devez supprimer le fichier en question, puis essayer à nouveau de cacher pop / apply et il devrait passer. Ne supprimez pas d'autres fichiers, uniquement ceux mentionnés par l'erreur.

Le problème: Git craint parfois. Lors de son exécution, git stash -uil inclut des fichiers non suivis (cool!) Mais il ne supprime pas ces fichiers non suivis et ne sait pas comment appliquer les fichiers non suivis cachés au-dessus des restes (pas cool!), Ce qui rend vraiment l' -uoption assez inutile.

qwertzguy
la source
3
J'aurais accepté cette réponse si c'était ma question. Merci @qwertzguy, votre réponse a résolu mon problème,
Kobus Myburgh
Ran dans le même problème moi-même, git stash pop ne s'appliquerait pas tant que je n'aurais pas supprimé les fichiers en question - puis j'ai rencontré un conflit avec un fichier qui a entraîné le rejet de la cachette. Mais plutôt que de supprimer les fichiers non suivis, il les a laissés derrière. Alors notez au futur moi, restez à l'écart degit stash -u
notzippy
Mauvais conseil si vous avez besoin de pièces des deux versions des fichiers concernés.
Walf
2
"il ne supprime pas ces fichiers non suivis" ... et ne les répertorie pas git stash show. Cette réponse a fait allumer l'ampoule.
jscs
2
plus un pour Git craint parfois.
Harish
29

Pour appliquer les différences de code dans la réserve sous forme de correctif, utilisez la commande suivante:

git stash show --patch | patch -p1
chiffrement
la source
11
Habituellement, il est préférable d'expliquer une solution au lieu de simplement publier quelques lignes de code anonyme. Vous pouvez lire Comment écrire une bonne réponse , et aussi Expliquer des réponses entièrement basées sur le code .
Massimiliano Kraus
Cela fonctionne pour moi car le correctif de git stash show --patchne contient pas les fichiers non suivis.
Steven Shaw
Cette réponse m'a beaucoup aidé car je n'ai pas pu ouvrir ma réserve en raison de nombreux changements dans mon repo depuis que la réserve avait été poussée.
Erik Finnman
1

Cela m'est arrivé de nombreuses fois, je cache les fichiers non suivis avec git stash -ulesquels finissent par être ajoutés au dépôt et je ne peux plus appliquer les modifications cachées.

Je n'ai pas trouvé de moyen de forcer git stash pop/applyle remplacement des fichiers, alors je supprime d'abord les copies locales des fichiers non suivis qui ont été cachés (faites attention car cela supprimera toutes les modifications qui n'ont pas été validées ), puis j'applique les modifications cachées :

rm `git ls-tree -r stash@{0}^3 --name-only`
git stash apply

Enfin, je l' utilise git status, git diffet d' autres outils pour vérifier et Réintégration parties des fichiers supprimés s'il y a quelque chose qui manque.


Si vous avez des modifications non validées que vous souhaitez conserver, vous pouvez d'abord créer une validation temporaire:

git add --all
git commit -m "dummy"
rm `git ls-tree -r stash@{0}^3 --name-only`
git stash apply

Utilisez les outils qui vous conviennent pour fusionner les modifications précédemment validées dans les fichiers locaux et supprimer la validation factice:

git reset HEAD~1
Helder Pereira
la source
0

Mon opération pop également bloquée était parce que les restes étaient ignorés fichiers restaient (voir le fichier .gitignore). Le statut Git m'a montré suivi et non suivi, mais mes activités n'ont pas nettoyé les fichiers ignorés.

Détails: j'avais utiliségit stash save -a , extrait le master pour compiler et voir le comportement d'origine, puis essayé de tout remettre pour continuer l'édition. Lorsque j'ai extrait ma branche et essayé de faire apparaître, mes fichiers ignorés étaient toujours là avant la sauvegarde de la réserve. En effet, l'extraction du maître n'a affecté que les fichiers validés - elle n'a pas effacé les fichiers ignorés. Donc, le pop a échoué, disant essentiellement qu'il ne voulait pas restaurer mes fichiers ignorés cachés au-dessus des fichiers qui étaient toujours là. Il est malheureux que je n'ai pas trouvé un moyen de démarrer une session de fusion avec eux.

En fin de compte, j'avais l'habitude git clean -f -d -xde supprimer les fichiers ignorés. Fait intéressant, sur mes ~ 30, 4 fichiers restaient encore après le nettoyage (enterrés dans des sous-répertoires). Je vais devoir déterminer dans quelle catégorie ils appartiennent, qu'ils ont dû être supprimés manuellement.

Puis mon pop a réussi.

désaffirmé
la source
0

Essaye ça:

git checkout stash -.

Nalan Madheswaran
la source
-1

Autre solution:

cd to/root/your/project

# Show what git will be remove
git clean -n

# If all is good
git clean -f

# If not all is good, see
git clean --help

# Finish
git stash pop
ktretyak
la source
L'erreur mentionnée dans la question est causée par un fichier qui existe à la fois dans la pile et dans le répertoire de travail. Le nettoyage ne le corrige que si ce fichier n'est pas suivi, ce qui n'est certainement pas toujours le cas (et pas le cas de l'OP, puisqu'il a obtenu le fichier d'un pull).
Xavier Poinas
-1

Avec Git 2.14.x / 2.15 (Q3 2017), la solution de qwertzguy de 2014 ne sera plus nécessaire.

Avant le troisième trimestre 2017, vous deviez supprimer le fichier en question, puis réessayer de cacher pop / apply.
Avec la prochaine version de Git, vous n'aurez plus à faire cela.

Voir commit bbffd87 (11 août 2017) de Nicolas Morey-Chaisemartin ( nmorey) .
(Fusionné par Junio ​​C Hamano - gitster- in commit 0ca2f32 , 23 août 2017)

stash: nettoyer les fichiers non suivis avant la réinitialisation

Si vous appelez git stash -uun référentiel qui contient un fichier qui n'est plus ignoré en raison d'une modification en cours du gitignorefichier, ce fichier est caché mais pas supprimé de l'arborescence de travail.
Cela est dû au fait de git-stashfaire d'abord un reset --hardqui efface la .gitignoremodification du fichier, puis de l'appeler git clean, en laissant le fichier intact.
Cela provoque un git stash popéchec en raison du fichier existant .

Ce patch bascule simplement l'ordre entre le nettoyage et la réinitialisation et ajoute un test pour ce cas d'utilisation.

VonC
la source
-1

Le moyen le plus sûr de suivre le stockage

git stash -u

Cela cachera tout, y compris les changements non mis en scène

git stash drop

une fois que vous avez fini de travailler dessus, pour supprimer votre réserve "sûre".

RahulMohan Kolakandy
la source
Comme expliqué dans stackoverflow.com/a/23743125/6309 , cela ne fonctionnerait pas toujours avec Git 2.14 ou moins. Cela fonctionnera avec Git 2.15: stackoverflow.com/a/46027357/6309
VonC