web-dev-qa-db-fra.com

Git stash: "Impossible d'appliquer à un arbre de travail sale, veuillez mettre en scène vos modifications"

J'essaie d'appliquer les modifications que j'ai cachées plus tôt avec git stash pop et obtenez le message:

Cannot apply to a dirty working tree, please stage your changes

Une suggestion sur la façon de gérer cela?

131
avernet

Quand je dois appliquer des modifications cachées à une copie de travail sale, par exemple pop plus d'un changeset de la cachette, j'utilise ce qui suit:

$ git stash show -p | git apply -3 && git stash drop

Fondamentalement, il

  1. crée un patch
  2. tuyaux qui à la commande appliquer
  3. s'il y a des conflits, ils devront être résolus via une fusion à 3 voies
  4. si appliquer (ou fusionner) a réussi, il supprime l'élément de stockage qui vient d'être appliqué ...

Je me demande pourquoi il n'y a pas de -f (forcer) option pour git stash pop qui devrait se comporter exactement comme le one-liner ci-dessus.

En attendant, vous voudrez peut-être ajouter ce one-liner comme alias git:

$ git config --global --replace-all alias.unstash \
   '!git stash show -p | git apply -3 && git stash drop'
$ git unstash

Merci à @SamHasler d'avoir souligné le -3 paramètre qui permet de résoudre les conflits directement via une fusion à 3 voies.

192
muhqu

Je le fais de cette façon:

git add -A
git stash apply

puis (éventuellement):

git reset
57
Sergii Mostovyi

Vous pouvez le faire sans avoir à cacher vos modifications actuelles en exportant la sauvegarde que vous souhaitez en tant que fichier de correctif et en l'appliquant manuellement.

Par exemple, supposons que vous souhaitiez appliquer stash @ {0} à un arbre sale:

  1. Exportez la cachette @ {0} en tant que patch:

    git stash show -p stash @ {0}> Stash0.patch

  2. Appliquez manuellement les modifications:

    git applique Stash0.patch

Si la deuxième étape échoue, vous devrez modifier le fichier Stash0.patch pour corriger les erreurs, puis réessayer git apply.

9
Ishan

Soit nettoyer votre répertoire de travail avec git reset, valider les modifications, ou, si vous voulez cacher les modifications en cours, essayez:

 $ git stash enregistrer "description des modifications en cours" 
 $ git stash pop stash @ {1} 

Cela stockera les modifications en cours, puis fera éclater la deuxième cachette de la pile de cachettes.

8
William Pursell

La solution de Mathias est certainement la plus proche d'une pop git stash --force (et vraiment, allez aux développeurs Git, prenons déjà cette option!)

Cependant, si vous souhaitez faire la même chose en utilisant uniquement les commandes git, vous pouvez:

  1. git commit -a -m "Fixme"
  2. git stash pop
  3. git commit -a --amend
  4. git reset HEAD ~

En d'autres termes, faites un commit (que nous ne pousserons jamais) de vos modifications actuelles. Maintenant que votre espace de travail est propre, ouvrez votre réserve. Maintenant, validez les modifications cachées en tant qu'amendement à votre validation précédente. Cela fait, vous avez maintenant les deux ensembles de modifications combinés en un seul commit ("Fixme"); réinitialisez simplement (--soft NOT --hard pour que rien ne soit réellement perdu) votre paiement à "un avant ce commit", et maintenant vous avez les deux ensembles de changements, complètement non validés.

** MODIFIER * *

Je viens de réaliser que c'est encore plus facile; vous pouvez ignorer complètement l'étape 3, alors ...

  1. git commit -a -m "Fixme"
  2. git stash pop
  3. git reset HEAD ~

(Validez les modifications en cours, supprimez les modifications cachées, réinitialisez ce premier commit pour que les deux ensembles de modifications soient combinés dans un état non validé.)

6
machineghost

J'ai également trouvé la solution de Mathias Leppich fonctionnant très bien, j'ai donc ajouté un alias pour cela à mon .gitconfig global

[alias]
        apply-stash-to-dirty-working-tree = !git stash show -p | git apply && git stash drop

Maintenant, je peux simplement taper

git apply-stash-to-dirty-working-tree

ce qui fonctionne très bien pour moi.

(Votre kilométrage peut varier sur ce long nom d'alias. Mais j'aime une dose de verbosité quand il s'agit de terminer bash.)

4
mat

Aucune de ces réponses ne fonctionne réellement si vous vous trouvez dans cette situation comme je l'ai fait aujourd'hui. Quel que soit le nombre git reset --hard c'est ce que j'ai fait, ça ne m'a mené nulle part. Ma réponse (pas officielle du tout était):

  1. Découvrez l'utilisation du hachage de la cachette git reflog --all
  2. Fusionnez ce hachage avec la branche qui vous intéresse
4
Dan Rosenstark

Vous pouvez appliquer une stash à un arbre "sale" en faisant git add pour mettre en scène toutes les modifications que vous avez apportées, nettoyant ainsi l'arbre. Ensuite vous pouvez git stash pop et appliquer les modifications cachées, pas de problème.

3
Chris Vandevelde

Vous avez des fichiers qui ont été modifiés mais non validés. Non plus:

git reset --hard HEAD (to bring everything back to HEAD)

ou, si vous souhaitez enregistrer vos modifications:

git checkout -b new_branch
git add ...
git commit
git checkout -b old_branch
git stash pop
2
brool

Je n'ai pas réussi à faire fonctionner la plupart d'entre eux; pour une raison quelconque, il pense toujours que j'ai des modifications locales dans un fichier. Je ne peux pas appliquer de stash, les correctifs ne s'appliqueront pas, checkout et reset --hard échouer. Ce qui a finalement fonctionné, c'était de sauvegarder la cachette en tant que branche avec git stash branch tempbranchname, puis faire une fusion de branche normale: git checkout master et git merge tempbranchname. De http://git-scm.com/book/en/Git-Tools-Stashing :

Si vous souhaitez tester plus facilement les modifications stockées, vous pouvez exécuter la branche git stash, qui crée une nouvelle branche pour vous, vérifie le commit sur lequel vous étiez lorsque vous avez stocké votre travail, réapplique votre travail là-bas, puis supprime le planque s'il s'applique avec succès

0
rwilson04

J'ai eu le même problème mais git n'avait aucun fichier modifié. Il s'avère que j'avais un fichier index.lock qui traînait. La supprimer a résolu le problème.

0
boxed