Comment décompresser uniquement certains fichiers?

388

J'ai caché mes changements. Maintenant, je veux décompresser seulement certains fichiers de la stash. Comment puis-je faire ceci?

morpheus
la source
4
Je pense que vous devez appliquer l'intégralité de la cachette, mais vous pouvez ensuite retaper sélectivement.
Richard
4
@AbdouTahiri Quel est le problème avec la cachette?
alex
32
@AbdouTahiri Uhhhh .. git stash est une fonctionnalité légitime et extrêmement utile. Je l'utilise quotidiennement. Disons, un collègue a besoin de moi pour revoir quelque chose mais je suis au milieu d'un ensemble de changements complexes. Je ne vais pas commettre une pile de code cassé juste pour pouvoir changer de branche. Je vais ranger, changer de branche, réviser, revenir en arrière, décrocher. Vous souciez-vous de préciser qui ou pourquoi git stash est soi-disant "non recommandé"? Ce n'est pas parce que votre histoire de git stash est confuse et difficile à lire que tout le monde l'est. Un ensemble de cache git désordonné est juste un mauvais flux de travail, pas un défaut de Git.
dudewad
6
@alex Rien. Rien de mal avec git stash. Continuez à l'utiliser.
dudewad

Réponses:

463

Comme mentionné ci-dessous , et détaillé dans " Comment extraire un seul fichier (ou des modifications apportées à un fichier) d'une git stash? ", Vous pouvez appliquer l'utilisation git checkoutou git showrestaurer un fichier spécifique.

git checkout stash@{0} -- <filename>

Cela écrase filename : assurez-vous que vous n'avez pas apporté de modifications locales, ou que vous souhaitiez peut-être fusionner le fichier caché à la place .

(Comme commenté par Jaime M. , pour certains shell comme tcsh où vous devez échapper aux caractères spéciaux, la syntaxe serait: git checkout 'stash@{0}' -- <filename>)

ou pour l'enregistrer sous un autre nom de fichier:

git show stash@{0}:<full filename>  >  <newfile>

(notez que voici <full filename>le chemin complet d'un fichier par rapport au répertoire supérieur d'un projet (pensez: par rapport à stash@{0})).

yucer suggère dans les commentaires :

Si vous souhaitez sélectionner manuellement les modifications que vous souhaitez appliquer à partir de ce fichier:

git difftool stash@{0}..HEAD -- <filename>

Vivek ajoute dans les commentaires :

On dirait que " git checkout stash@{0} -- <filename>" restaure la version du fichier au moment où le stash a été effectué - il n'applique PAS (juste) les changements stashés pour ce fichier.
Pour faire ce dernier:

git diff stash@{0}^1 stash@{0} -- <filename> | git apply

(comme commenté par peterflynn , vous pourriez avoir besoin | git apply -p1dans certains cas, la suppression d' un ( p1) barre oblique de chemins diff traditionnels)


Comme commenté: "unstash" ( git stash pop), puis:

  • ajoutez ce que vous souhaitez conserver à l'index ( git add)
  • planque le reste: git stash --keep-index

Le dernier point est ce qui vous permet de conserver certains fichiers tout en en cachant d'autres.
Il est illustré dans " Comment cacher un seul fichier parmi plusieurs fichiers qui ont été modifiés ".

VonC
la source
5
Cela ne fonctionne pas si vous ne pouvez pas le faire en git stash popraison de conflits de fichiers. La réponse de Balamurugan A a fait l'affaire pour moi dans ce cas.
Andrey
1
Si vous souhaitez sélectionner manuellement les modifications que vous souhaitez appliquer à partir de ce fichier, vous pouvez utiliser git difftool stash @ {0} .. HEAD - <nomfichier>
yucer
5
On dirait que "git checkout stash @ {0} - <nomfichier>" restaure la version du fichier au moment où le stash a été effectué - il n'applique PAS (seulement) les modifications stockées pour ce fichier. Pour ce faire: "git diff stash @ {0} ^ 1 stash @ {0} - <nomfichier> | git apply"
Vivek
1
@JaimeM. Je vous remercie. J'ai inclus votre commentaire dans la réponse pour plus de visibilité.
VonC
1
En supposant que cela unstashsignifie pop, comme il me semble que ce serait probablement le cas dans la plupart des cas, cela ne répond que partiellement à la question. Comment supprimez-vous ensuite les pièces appliquées de manière sélective de la cachette afin d'éviter des conflits ultérieurs et / ou de la confusion lors du saut des modifications restantes?
DylanYoung
115
git checkout stash@{N} <File(s)/Folder(s) path> 

Par exemple. Pour restaurer uniquement le fichier ./test.c et le dossier ./include à partir du dernier fichier caché,

git checkout stash@{0} ./test.c ./include
Balamurugan A
la source
12
Ceci est la bonne réponse! Commande sur une seule ligne pour appliquer uniquement les modifications cachées à partir de fichiers spécifiques, fonctionne comme un charme!
4levels
1
Pour appliquer (juste) les modifications cachées pour le fichier: "git diff stash @ {N} ^ 1 stash @ {N} - <nomfichier> | git apply"
Vivek
Cela fonctionne aussi pour moi. Il vous suffit de sélectionner de manière sélective les fichiers nécessaires à utiliser depuis stash et vous avez terminé. J'étais coincé dans ce -adrapeau que j'avais utilisé lors de la création de la cachette.
Rajeev Ranjan
1
@ 4levels Je pense que "appliquer les changements cachés" n'est pas ce qui se passe, non? Je pense que "remplacer tout ce que vous avez avec la copie de la cachette" est ce qui se passe.
msouth
35

Je pense que la réponse de VonC est probablement ce que vous voulez, mais voici un moyen de faire un "git apply" sélectif:

git show stash@{0}:MyFile.txt > MyFile.txt
Mike Monkiewicz
la source
4
Cela peut être ce que vous voulez dans certains cas, mais sachez que cette commande écrasera plutôt qu'elle ne fusionnera avec les modifications du répertoire de travail.
Rhubbarb
Cela fonctionne pour moi, car je voulais juste copier un fichier qui n'existe que dans la cachette et ne se souciait de checkoutrien.
Tom Russell
1
Pour Windows PowerShell: git show stash@`{0`}:Path/To/MyFile.txt |sc Path/To/MyFile.txt- les backticks sont nécessaires pour que PS n'interprète pas spécialement les accolades, et sccela est nécessaire car l' >opérateur de PS par défaut est UTF-16 (en fait UCS-2), ce qui n'est probablement pas ce que vous voulez. La réponse de @Balamurugan A ne souffre pas de ces problèmes.
Ian Kemp
19

Liste d'abord toutes les cachettes

git stash list

stash@{0}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{1}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{2}: WIP on master: 7e450c81 Merge branch 'Offlineseite'

Ensuite, montrez quels fichiers sont dans la cachette (permet de choisir la cachette 1):

git stash show 1 --name-only

//Hint: you can also write
//git stash show stash@{1} --name-only

 ajax/product.php
 ajax/productPrice.php
 errors/Company/js/offlineMain.phtml
 errors/Company/mage.php
 errors/Company/page.phtml
 js/konfigurator/konfigurator.js

Ensuite, appliquez le fichier que vous aimez:

git checkout stash@{1} -- <filename>

ou dossier entier:

git checkout stash@{1} /errors

Il fonctionne également sans --mais il est recommandé de les utiliser. Voir cet article.

Il est également classique de reconnaître un double tiret comme un signal pour arrêter l'interprétation des options et de traiter littéralement tous les arguments suivants.

Noir
la source
1
C'est plus clair avec cette modification. +1
VonC
1
J'ai essayé de nombreuses façons et cette façon était celle dont j'avais besoin. J'ai été confronté à un problème qui a git stash popgénéré une erreur pour les fichiers non suivis. Merci.
Ramin Firooz
10

Si vous git stash pop(sans conflits), il supprimera la cachette après son application. Mais si vous git stash applyappliquez le correctif sans le supprimer de la liste cachée. Ensuite, vous pouvez annuler les modifications indésirables avecgit checkout -- files...

Ben Jackson
la source
2
Pour clarifier la partie des conflits de ce message, si vous git stash popet il y a des conflits, vous devrez les corriger manuellement et la cachette ne sera PAS supprimée.
Thomas McCabe du
6

Encore une façon:

git diff stash@{N}^! -- path/to/file1 path/to/file2  | git apply -R
Lacho Tomov
la source
2
C'est la seule réponse correcte de l'OMI. Utiliser checkoutou showécrasera aveuglément votre fichier au lieu d'appliquer simplement des modifications. "Une autre façon" est un euphémisme.
cambunctious
1
Je ne reçois pas le path/to/file2comme vous voulez faire la différence avec le même fichier dans votre espace de travail. Laisser de côté le deuxième chemin me convient parfaitement. - Et je reçois un message d'erreur en utilisant l' -Roption ("appliquer le patch à l'envers", en essayant de patcher la version cachée?!). Donc, ma version de travail ressemble git diff stash@{N}^! -- path/to/file | git apply -.
ThomasH
"patch a échoué"? Essayez une fusion à trois. ...| git apply -3 -
John Mee
6

Pour les utilisateurs de Windows: les accolades ont une signification particulière dans PowerShell. Vous pouvez soit entourer de guillemets simples ou échapper avec backtick. Par exemple:

git checkout 'stash@{0}' YourFile

Sans cela, vous pouvez recevoir une erreur:

Unknown switch 'e'

Janac Meena
la source
3
Pleines notes à PowerShell pour le message utilisateur le moins utile que j'ai vu ce mois-ci.
holdenweb