Cacher un seul fichier parmi plusieurs fichiers modifiés avec Git?

3071

Comment puis-je cacher un seul des multiples fichiers modifiés sur ma branche?

Rachel
la source
109
Je ne pense pas que la réponse acceptée de @ bukzor soit une réponse correcte à la question telle qu'elle a été posée. git stash --keep-indexconserve l'index, mais il cache tout - à la fois dans l'index et à l'extérieur.
Raman
@Antonio Il me semble que votre prime devrait en fait être une question distincte, car la question d'origine n'a rien à voir avec TortoiseGit en particulier.
JesusFreke
1
@JesusFreke Yep, étant donné le résultat, j'aurais pu épargner 50 répétitions :) C'est juste que c'est la question à laquelle vous êtes redirigé si vous essayez de rechercher "tortoisegit cachette partielle". Tortoisegit ne semble pas être un sujet populaire ici stackoverflow.com/questions/tagged/tortoisegit
Antonio
7
>>>>>>>>> git diff -- *filename* > ~/patchpuis git checkout -- *filename*et plus tard, vous pouvez git apply ~/patch
réappliquer
36
La plupart des réponses ci-dessous sont obsolètes. Depuis Git 2.13 (Q2 2017), il est pris en charge avec git stash push [--] [<pathspec>...].
Ohad Schneider

Réponses:

1372

Avertissement : la réponse suivante est pour git avant git 2.13. Pour git 2.13 et plus, consultez une autre réponse plus bas .


Attention

Comme indiqué dans les commentaires, cela met tout dans la cachette, à la fois mis en scène et non mis en scène. --Keep-index laisse juste l'index seul une fois le stash terminé. Cela peut entraîner des conflits de fusion lorsque vous ouvrez ultérieurement la réserve.


Cela stockera tout ce que vous n'avez pas ajouté précédemment. Juste git addce que vous voulez garder, puis exécutez-le.

git stash --keep-index

Par exemple, si vous souhaitez diviser un ancien commit en plusieurs changements, vous pouvez utiliser cette procédure:

  1. git rebase -i <last good commit>
  2. Marquer certains changements comme edit.
  3. git reset HEAD^
  4. git add <files you want to keep in this change>
  5. git stash --keep-index
  6. Réparez les choses si nécessaire. N'oubliez pas git addles modifications.
  7. git commit
  8. git stash pop
  9. Répétez, à partir de # 5, si nécessaire.
  10. git rebase --continue
bukzor
la source
47
Je trouve cette approche beaucoup plus simple: stackoverflow.com/a/5506483/457268
k0pernikus
561
Je ne sais pas pourquoi cela fait l'objet d'un vote positif. Tout le monde doit avoir une attente différente de moi. Le message d'origine demande "comment puis-je cacher juste une partie des modifications non validées?" Lorsque j'utilise git stash save -k, oui, l'index (en vert git stat) est conservé, mais l' ensemble des modifications (à la fois vert et rouge) va dans la cachette. Cela viole la demande du PO, "ne cache que quelques modifications". Je veux ranger juste une partie du rouge (pour une utilisation future).
Pistos
70
Si vous êtes plus intéressé par la réponse à la question posée par @Pistos (comme je l'étais), alors regardez ici: stackoverflow.com/questions/5506339/…
Raman
27
@Raman: Excellent! git stash -pest exactement ce que je cherchais. Je me demande si ce commutateur n'a été ajouté que récemment.
Pistos
14
ATTENTION: git stash --keep-indexest cassé. Si vous apportez plus de modifications, essayez git stash popensuite d'obtenir des conflits de fusion car la cachette comprend les fichiers modifiés que vous avez conservés, pas seulement ceux que vous n'avez pas conservés. Par exemple: je modifie les fichiers A et B, puis je stocke B, car je veux tester les modifications dans A; Je trouve un problème avec A que je corrige ensuite; Je commets A; Maintenant, je ne peux pas déchausser car une ancienne version de A est dans la cachette sans raison valable, provoquant un conflit de fusion. Dans la pratique, A et B peuvent avoir de nombreux fichiers, peut-être même des images binaires ou quelque chose, donc je dois essentiellement abandonner et perdre B.
rjmunro
3015

Vous pouvez également utiliser git stash save -p "my commit message". De cette façon, vous pouvez sélectionner quels morceaux doivent être ajoutés à la stash, des fichiers entiers peuvent également être sélectionnés.

Vous serez invité avec quelques actions pour chaque morceau:

   y - stash this hunk
   n - do not stash this hunk
   q - quit; do not stash this hunk or any of the remaining ones
   a - stash this hunk and all later hunks in the file
   d - do not stash this hunk or any of the later hunks in the file
   g - select a hunk to go to
   / - search for a hunk matching the given regex
   j - leave this hunk undecided, see next undecided hunk
   J - leave this hunk undecided, see next hunk
   k - leave this hunk undecided, see previous undecided hunk
   K - leave this hunk undecided, see previous hunk
   s - split the current hunk into smaller hunks
   e - manually edit the current hunk
   ? - print help
konrad.kruczynski
la source
5
Ce n'était pas. Il a été emprunté à Darcs, environ 7 ans après les faits.
nomen
6
Je suis accro à TortoiseGit. Cependant TortoiseGit ne prend pas en charge stash -p. J'attribue cette réponse car elle reste la plus interactive / conviviale.
Antonio
27
vous voudrez peut-être ajouter git stash save -p my stash message:; puisque l'ordre de l'argumenst n'est pas très intuitif ...
Chris Maes
15
Entre cela et git log -p, je pense que le -pdrapeau doit signifier "fais la chose cool que je veux mais je ne sais pas comment l'exprimer".
Kyle Strand
2
pourquoi diable cette excellente réponse est en 12ème position ?? après toutes ces réponses 0, +1, +2 ??????
DenisFLASH
550

Étant donné que git consiste fondamentalement à gérer tout le contenu et l'index du référentiel (et non un ou plusieurs fichiers) git stash, il n'est pas surprenant queavec le répertoire de travail.

En fait, depuis Git 2.13 (Q2 2017), vous pouvez cacher des fichiers individuels, avec git stash push:

git stash push [--] [<pathspec>...]

Quand pathspecest donné à ' git stash push', la nouvelle cachette enregistre les états modifiés uniquement pour les fichiers qui correspondent à la spécification de chemin Voir "Modifications de la cachette dans des fichiers spécifiques " pour plus d'informations.

Exemple simplifié:

 git stash push path/to/file

Le scénario de test pour cette fonctionnalité montre quelques options supplémentaires désactivées:

test_expect_success 'stash with multiple pathspec arguments' '
    >foo &&
    >bar &&
    >extra &&
    git add foo bar extra &&

    git stash push -- foo bar &&   

    test_path_is_missing bar &&
    test_path_is_missing foo &&
    test_path_is_file extra &&

    git stash pop &&
    test_path_is_file foo &&
    test_path_is_file bar &&
    test_path_is_file extra

La réponse originale (ci-dessous, juin 2010) concernait la sélection manuelle de ce que vous souhaitez ranger.

Commentaires de Casebash :

Ceci (la stash --patchsolution d'origine) est bien, mais souvent j'ai modifié beaucoup de fichiers, donc l'utilisation du patch est ennuyeuse

bukzor de réponse (upvoted, Novembre 2011) propose une solution plus pratique, basée sur
git add+git stash --keep-index .
Allez voir et voter pour sa réponse, qui devrait être la réponse officielle (au lieu de la mienne).

À propos de cette option, chhh souligne un autre workflow dans les commentaires:

vous devriez « git reset --soft» après stash un pour obtenir votre dos de mise en scène claire:
Pour se rendre à l'état d' origine - qui est une zone de mise en scène claire et avec seulement une sélection de modifications non mis en scène, on pourrait doucement réinitialiser l'index pour obtenir (sans commettre quelque chose comme vous - bukzor - l'a fait).


(Réponse originale juin 2010: plan de travail manuel)

Pourtant, cela git stash save --patchpourrait vous permettre d'obtenir le stockage partiel que vous recherchez:

Avec --patch, vous pouvez sélectionner interactivement des morceaux dans le diff entre HEAD et l'arborescence de travail à ranger.
L'entrée de stash est construite de telle sorte que son état d'index est le même que l'état d'index de votre référentiel, et son arbre de travail contient uniquement les modifications que vous avez sélectionnées de manière interactive. Les modifications sélectionnées sont ensuite annulées à partir de votre arbre de travail.

Cependant, cela enregistrera l'index complet (qui peut ne pas être ce que vous voulez car il peut inclure d'autres fichiers déjà indexés) et un arbre de travail partiel (qui pourrait ressembler à celui que vous souhaitez ranger).

git stash --patch --no-keep-index

pourrait être un meilleur ajustement.


Si --patchcela ne fonctionne pas, un processus manuel peut:

Pour un ou plusieurs fichiers, une solution intermédiaire serait de:

  • les copier en dehors du repo Git
    (En fait, eleotlecram propose une alternative intéressante )
  • git stash
  • recopiez-les
  • git stash # cette fois, seuls les fichiers que vous souhaitez sont cachés
  • git stash pop stash@{1} # réappliquez toutes vos modifications de fichiers
  • git checkout -- afile # réinitialiser le fichier au contenu HEAD, avant toute modification locale

À la fin de ce processus plutôt lourd, vous n'aurez qu'un ou plusieurs fichiers cachés.

VonC
la source
3
C'est bien, mais j'ai souvent modifié beaucoup de fichiers, donc utiliser le patch est ennuyeux
Casebash
6
@VonC: C'est bien d'avoir une seule réponse par réponse. En outre, copier-coller les réponses des autres dans les vôtres est une mauvaise manière.
bukzor
3
@bukzor: Je suis désolé si ma réponse modifiée semble incorrecte. Ma seule intention était de donner plus de visibilité à votre réponse. J'ai retravaillé mon message afin de clarifier cette intention.
VonC
1
@Kal: true, stackoverflow.com/a/13941132/6309 suggère un git reset(mixte)
VonC
3
git is fundamentally about managing a all repository content and index and not one or several files- cette mise en œuvre éclipse le problème résolu; c'est une explication, mais pas une justification. Tout système de contrôle de source consiste à "gérer plusieurs fichiers". Regardez simplement quels commentaires sont les plus votés.
Victor Sergienko
90

Quand git stash -p(ou git add -pavec stash --keep-index) serait trop encombrant, je l'ai trouvé plus facile à utiliser diff, checkoutet apply:

Pour «cacher» un fichier / répertoire particulier uniquement:

git diff path/to/dir > stashed.diff
git checkout path/to/dir

Puis après

git apply stashed.diff
bleuté
la source
1
Alternative intéressante à celle que git add -pj'ai mentionnée dans ma propre réponse ci-dessus. +1.
VonC
11
Notez que si vous avez des fichiers binaires (comme les PNG), ils ne seront pas sortis dans le fichier diff. Ce n'est donc pas une solution à 100%.
void.pointer
1
@RobertDailey: C'est un point intéressant pour moi, comme git diff > file.diffet git applysont mes outils habituels stash partiels. Je devrais peut-être envisager de passer à git stash -pdes ensembles de modifications plus importants.
thekingoftruth
1
@thekingoftruth Voici l'alias que j'utilise pour créer des fichiers de patch, et il fait des binaires de soutien: patch = log --pretty=email --patch-with-stat --reverse --full-index --binary. Notez cependant que cela nécessite vos modifications pour que le correctif soit validé.
void.pointer
2
Cela ne fonctionnait pas correctement pour moi si le fichier à cacher était quelque chose comme ça ../../foo/bar.txt. Le correctif génère OK, mais je dois ensuite passer à la racine du référentiel pour appliquer le correctif. Donc, si vous rencontrez des problèmes avec cela - assurez-vous de le faire à partir du répertoire racine du référentiel.
Michael Anderson
86

Utilisez git stash push, comme ceci:

git stash push [--] [<pathspec>...]

Par exemple:

git stash push -- my/file.sh

Ceci est disponible depuis Git 2.13, sorti au printemps 2017.

sandstrom
la source
1
Mais je mentionne git stash pushdéjà dans ma réponse ci-dessus en mars dernier, il y a 5 mois. Et j'ai détaillé cette nouvelle commande Git 2.13 ici: stackoverflow.com/a/42963606/6309 .
VonC
Je suis heureux que Git progresse si rapidement, cela n'a pas été possible pendant longtemps, puis la version 2.13 est sortie et soudain, une solution simple est disponible!
sandstrom
1
@VonC vous avez raison, vous mentionnez également la bonne réponse, cependant, entre les deux réponses, celle-ci est plus facile à lire (pas de texte déroutant et il y a aussi un exemple). Peut-être qu'ils auraient dû modifier votre réponse à la place
Utopik
@Utopik Vous m'aviez dit "vous avez raison" ... mais oui, j'ai modifié ma réponse pour inclure un exemple.
VonC
Peut-on alors utiliser git stash applypour récupérer les modifications cachées?
Tchad
49

Disons que vous avez 3 fichiers

a.rb
b.rb
c.rb

et vous ne voulez cacher que b.rb et c.rb mais pas a.rb

vous pouvez faire quelque chose comme ça

# commit the files temporarily you don't want to stash
git add a.rb
git commit -m "temp" 

# then stash the other files
git stash save "stash message"

# then undo the previous temp commit
git reset --soft HEAD^
git reset

Et vous avez terminé! HTH.

venkatareddy
la source
29

Une autre façon de procéder:

# Save everything
git stash 

# Re-apply everything, but keep the stash
git stash apply

git checkout <"files you don't want in your stash">

# Save only the things you wanted saved
git stash

# Re-apply the original state and drop it from your stash
git stash apply stash@{1}
git stash drop stash@{1}

git checkout <"files you put in your stash">

Je l'ai trouvé après être (encore une fois) venu sur cette page et je n'ai pas aimé les deux premières réponses (la première réponse ne répond tout simplement pas à la question et je n'aimais pas vraiment travailler avec le -pmode interactif).

L'idée est la même que ce que @VonC a suggéré d'utiliser des fichiers en dehors du référentiel, vous enregistrez les modifications que vous voulez quelque part, supprimez les modifications que vous ne voulez pas dans votre stash, puis réappliquez les modifications que vous avez déplacées. Cependant, j'ai utilisé la cachette git comme "quelque part" (et en conséquence, il y a une étape supplémentaire à la fin: supprimer les obstacles que vous avez mis dans la cachette, car vous les avez également déplacés).

Jaspe
la source
1
je préfère le plus cette approche. Il fournit un flux de travail facile en tortoisegit en utilisant uniquement les commandes stash et revert.
Mark Ch
Il n'est pas conseillé de se référer aux réponses sur les SO en utilisant des positions. Les positions changent à mesure que les notes changent.
Bryan Ash
2
@BryanAsh Eh bien, ce n'est pas comme si c'était important ici. Je donne une anecdote plutôt que de me référer vraiment aux autres réponses. Le message est que je n'aimais pas les réponses que la communauté aimait et pas ce que ces réponses contiennent réellement. En outre, l'écart de 900 votes entre la deuxième et la troisième réponse rend peu probable que cela change dans un proche avenir, et si cela devait changer, je peux toujours le modifier pour dire "le plus haut pour les réponses à l'époque". Vraiment, je ne vois pas en quoi c'est un problème dans cette situation.
Jasper
23

Mise à jour (14/02/2015) - J'ai un peu réécrit le script, pour mieux gérer le cas des conflits, qui devraient maintenant être présentés comme des conflits non fusionnés plutôt que des fichiers .rej.


Je trouve souvent plus intuitif de faire l'inverse de l'approche de @ bukzor. C'est-à-dire, pour mettre en scène certains changements, puis ne cacher que ces changements par étapes.

Malheureusement, git n'offre pas de cachette git --only-index ou similaire, j'ai donc préparé un script pour le faire.

#!/bin/sh

# first, go to the root of the git repo
cd `git rev-parse --show-toplevel`

# create a commit with only the stuff in staging
INDEXTREE=`git write-tree`
INDEXCOMMIT=`echo "" | git commit-tree $INDEXTREE -p HEAD`

# create a child commit with the changes in the working tree
git add -A
WORKINGTREE=`git write-tree`
WORKINGCOMMIT=`echo "" | git commit-tree $WORKINGTREE -p $INDEXCOMMIT`

# get back to a clean state with no changes, staged or otherwise
git reset -q --hard

# Cherry-pick the index changes back to the index, and stash.
# This cherry-pick is guaranteed to succeed
git cherry-pick -n $INDEXCOMMIT
git stash

# Now cherry-pick the working tree changes. This cherry-pick may fail
# due to conflicts
git cherry-pick -n $WORKINGCOMMIT

CONFLICTS=`git ls-files -u`
if test -z "$CONFLICTS"; then
    # If there are no conflicts, it's safe to reset, so that
    # any previously unstaged changes remain unstaged
    #
    # However, if there are conflicts, then we don't want to reset the files
    # and lose the merge/conflict info.
    git reset -q
fi

Vous pouvez enregistrer le script ci-dessus git-stash-indexquelque part sur votre chemin, puis l'invoquer en tant que git stash-index

# <hack hack hack>
git add <files that you want to stash>
git stash-index

Maintenant, la cachette contient une nouvelle entrée qui ne contient que les modifications que vous aviez mises en scène, et votre arborescence de travail contient toujours toutes les modifications non mises en scène.

Dans certains cas, les modifications de l'arborescence de travail peuvent dépendre des modifications d'index, donc lorsque vous planifiez les modifications d'index, les modifications de l'arborescence de travail ont un conflit. Dans ce cas, vous obtiendrez les conflits non fusionnés habituels que vous pouvez résoudre avec git merge / git mergetool / etc.

JesusFreke
la source
Recommander à la pushdplace cdet popdà la fin du script, donc si le script réussit, l'utilisateur se retrouve dans le même répertoire qu'avant de l'exécuter.
Nate
1
@Nate: pour autant que je sache, cela ne devrait changer le répertoire de l'utilisateur que s'il a trouvé le script. Si vous exécutez le script normalement (~ / bin / git-stash-index), ou via git (git stash-index), il s'exécute dans une session de terminal distincte, et toute modification du répertoire de travail dans cette session n'affecte pas le répertoire de travail dans la session de terminal de l'utilisateur. Êtes-vous au courant d'un cas d'utilisation courant lorsque ce n'est pas vrai? (autre que l'approvisionnement du script, que je ne considérerais pas comme "commun")
JesusFreke
20

Si vous ne souhaitez pas spécifier un message avec vos modifications cachées, passez le nom de fichier après un double tiret.

$ git stash -- filename.ext

S'il s'agit d'un fichier non suivi / nouveau, vous devrez d'abord le mettre en scène.

Cette méthode fonctionne dans les versions git 2.13+

Sealocal
la source
Cette réponse est verbeuse, c'est concis. Si cela aide quelqu'un, je le laisse. Personne sur cette page ne mentionne cette syntaxe et ce résultat - ils mentionnent plutôt `git stash push`.
sealocal
C'est la réponse que je cherchais. Merci! +1
nicodp
19

Étant donné que la création de branches dans Git est triviale, vous pouvez simplement créer une branche temporaire et y archiver les fichiers individuels.

shangxiao
la source
2
Vous ne pouvez pas créer une branche avec des modifications non échelonnées. Vous pouvez facilement déplacer toutes les modifications vers une nouvelle branche (stash / stash pop) mais vous revenez à la case départ: comment tester votre branche avec seulement certaines de ces modifications, sans perdre les autres?
bukzor
7
Vous ne pouvez pas changer de branche si vous avez des changements locaux. Cependant, vous pouvez créer une nouvelle branche et ajouter / valider des fichiers de manière sélective, puis créer une autre branche et faire la même chose récursivement ... puis extraire la branche d'origine et fusionner de manière sélective. Je viens de le faire. Cela semble en fait la façon naturelle de faire les choses, car vous créez essentiellement des branches de fonctionnalités.
iain
3
@iain vous pouvez changer de branche si vous avez des changements locaux, tant qu'ils ne nécessitent pas de fusion. Voir Exemple Gist . Cela est vrai à partir de Git v2.7.0 au moins.
Colin D Bennett
18

Vous pouvez simplement faire ceci:

git stash push "filename"

ou avec un message optionnel

git stash push -m "Some message" "filename"
vinodsaluja
la source
1
Cela n'ajoute rien de nouveau. Git stash push est déjà mentionné dans plusieurs réponses
JesusFreke
12

Enregistrez le code suivant dans un fichier, par exemple, nommé stash. L'utilisation est stash <filename_regex>. L'argument est l'expression régulière du chemin complet du fichier. Par exemple, pour ranger un / b / c.txt, stash a/b/c.txtou stash .*/c.txt, etc.

$ chmod +x stash
$ stash .*.xml
$ stash xyz.xml

Code à copier dans le fichier:

#! /usr/bin/expect --
log_user 0
set filename_regexp [lindex $argv 0]

spawn git stash -p

for {} 1 {} {
  expect {
    -re "diff --git a/($filename_regexp) " {
      set filename $expect_out(1,string)
    }
    "diff --git a/" {
      set filename ""
    }
    "Stash this hunk " {
      if {$filename == ""} {
        send "n\n"
      } else {
        send "a\n"
        send_user "$filename\n"
      }
    }
    "Stash deletion " {
      send "n\n"
    }
    eof {
      exit
    }
  }
}
abricot
la source
2
Grande méthode. J'aurais choisi cela comme réponse. Astuce pour les futurs lecteurs: vous devez correspondre sur le chemin complet. par exemple, stash subdir / foo.c
er0
12

Juste au cas où vous voudriez dire supprimer les changements chaque fois que vous utilisez git stash(et n'utilisez pas vraiment git stash pour le ranger temporairement), dans ce cas, vous pouvez utiliser

git checkout -- <file>

[ NOTE ]

C'est git stashjuste une alternative plus rapide et simple à la ramification et à la réalisation de tâches.

Devesh
la source
8

Le problème avec la solution `` intermédiaire '' de VonC de copier des fichiers vers l'extérieur du référentiel Git est que vous perdez les informations de chemin, ce qui rend la copie d'un tas de fichiers plus tard un peu compliquée.

A trouver plus facile d'utiliser tar (des outils similaires le feront probablement) au lieu de copier:

  • tar cvf /tmp/stash.tar chemin / vers / certains / fichier chemin / vers / certains / autres / fichier (... etc.)
  • git checkout path / to / some / file path / to / some / other / file
  • git stash
  • tar xvf /tmp/stash.tar
  • etc. (voir la suggestion «intermédiaire» de VonC)
eleotlecram
la source
checkout -fn'est pas nécessaire, checkout(sans -f) suffit, j'ai mis à jour la réponse.
eleotlecram
8

Parfois, j'ai effectué un changement sans rapport avec ma branche avant de l'avoir validé, et je veux le déplacer vers une autre branche et le valider séparément (comme master). Je fais ça:

git stash
git checkout master
git stash pop
git add <files that you want to commit>
git commit -m 'Minor feature'
git stash
git checkout topic1
git stash pop
...<resume work>...

Notez que le premier stash& stash poppeut être éliminé, vous pouvez reporter toutes vos modifications à la mastersuccursale lors de votre paiement, mais uniquement s'il n'y a pas de conflits. De plus, si vous créez une nouvelle branche pour les modifications partielles, vous aurez besoin de la cachette.

Vous pouvez le simplifier en supposant qu'aucun conflit et aucune nouvelle branche:

git checkout master
git add <files that you want to commit>
git commit -m 'Minor feature'
git checkout topic1
...<resume work>...

La cachette n'est même pas nécessaire ...

void.pointer
la source
8

Cela peut être fait facilement en 3 étapes en utilisant SourceTree.

  1. Validez temporairement tout ce que vous ne voulez pas cacher.
  2. Git ajoutez tout le reste, puis rangez-le.
  3. Pop votre commit temporaire en exécutant git reset, en ciblant le commit avant votre commit temporaire.

Tout cela peut être fait en quelques secondes dans SourceTree, où vous pouvez simplement cliquer sur les fichiers (ou même les lignes individuelles) que vous souhaitez ajouter. Une fois ajoutés, il suffit de les valider dans un commit temporaire. Ensuite, cochez la case pour ajouter toutes les modifications, puis cliquez sur cachette pour tout cacher. Avec les changements cachés, jetez un œil à votre liste de commit et notez le hachage pour le commit avant votre commit temporaire, puis exécutez 'git reset hash_b4_temp_commit', ce qui revient à "sauter" le commit en réinitialisant votre branche sur le s'engager juste avant. Maintenant, il ne vous reste que ce que vous ne vouliez pas cacher.

Triynko
la source
8

J'utiliserais git stash save --patch. Je ne trouve pas l'interactivité ennuyeuse car il y a des options pour appliquer l'opération souhaitée à des fichiers entiers.

Raffi Khatchadourian
la source
3
Étonné qu'il y ait si peu de soutien pour cette réponse, c'est la meilleure solution sans avoir besoin d'un essai.
robstarbuck
Certainement la bonne réponse, git stash -pvous permet de cacher un fichier entier rapidement et de quitter ensuite.
Richard Dally
7

Chaque réponse ici est tellement compliquée ...

Qu'en est-il de "cacher":

git diff /dir/to/file/file_to_stash > /tmp/stash.patch
git checkout -- /dir/to/file/file_to_stash

Ceci pour faire revenir le changement de fichier:

git apply /tmp/stash.patch

Exactement le même comportement que de cacher un fichier et de le réinsérer.

Christophe Fondacci
la source
Je l'ai essayé mais rien ne se passe. Quand je git applyn'ai aucune erreur mais que les changements ne sont pas non plus rapportés
ClementWalter
Le fichier de correctif que vous avez généré dans / tmp a probablement été supprimé. Vous avez peut-être redémarré entre le diff et l'application. Essayez un autre emplacement plus permanent. Ça marche. Vérifiez également le contenu du fichier de correctif.
Christophe Fondacci
4

J'ai examiné les réponses et les commentaires à ce sujet et un certain nombre de fils similaires. N'oubliez pas qu'aucune des commandes suivantes n'est correcte dans le but de pouvoir stocker des fichiers spécifiques suivis / non suivis :

  • git stash -p (--patch): sélectionnez les morceaux manuellement, à l'exclusion des fichiers non suivis
  • git stash -k (--keep-index): stockez tous les fichiers suivis / non suivis et conservez-les dans le répertoire de travail
  • git stash -u (--include-untracked): cache tous les fichiers suivis / non suivis
  • git stash -p (--patch) -u (--include-untracked): commande non valide

Actuellement, la méthode la plus raisonnable pour pouvoir stocker des fichiers spécifiques suivis / non suivis consiste à:

  • Validez temporairement les fichiers que vous ne voulez pas cacher
  • Ajouter et ranger
  • Pop le commit temporaire

J'ai écrit un script simple pour cette procédure dans une réponse à une autre question , et il existe des étapes pour effectuer la procédure dans SourceTree ici .

ZimbiX
la source
4

Solution

Changements locaux:

  • fichier_A (modifié) non mis en scène
  • file_B (modifié) non monté
  • file_C (modifié) non mis en scène

Pour créer un stash "my_stash" avec seulement les modifications sur file_C :

1. git add file_C
2. git stash save --keep-index temp_stash
3. git stash save my_stash
4. git stash pop stash@#{1}

Terminé.


Explication

  1. ajoutez file_C à la zone de transit
  2. créer une cachette temporaire nommée "temp_stash" et conserver les modifications sur file_C
  3. créer la cachette souhaitée ("my_stash") avec seulement les modifications sur file_C
  4. appliquez les modifications dans "temp_stash" (file_A et file_B) sur votre code local et supprimez la stash

Vous pouvez utiliser git status entre les étapes pour voir ce qui se passe.

Alex 75
la source
3

Lorsque vous essayez de basculer entre deux branches, cette situation se produit.

Essayez d'ajouter les fichiers à l'aide de " git add filepath".

Exécutez plus tard cette ligne

git stash --keep-index

Sireesh Yarlagadda
la source
3

Pour ranger un seul fichier, utilisez git stash --patch [file].

Cela va rapidement: Stash this hunk [y,n,q,a,d,j,J,g,/,e,?]? ?. Tapez simplement a(cachez ce morceau et tous les morceaux suivants dans le fichier) et tout va bien.

Vinicius Brasil
la source
Manquant pushcomme dansgit stash push --patch [file]
Filipe Esperandio
@FilipeEsperandio pushne fonctionne que dans les versions plus récentes de Git, autrefois save. Dans les deux cas pushou savesont implicites en appelant stash: "Appeler git stash sans aucun argument équivaut à git stash push", docs
patrick
2

Situation similaire. Je me suis engagé et j'ai réalisé que ce n'était pas bien.

git commit -a -m "message"
git log -p

Sur la base des réponses, cela m'a aidé.

# revert to previous state, keeping the files changed
git reset HEAD~
#make sure it's ok
git diff
git status
#revert the file we don't want to be within the commit
git checkout specs/nagios/nagios.spec
#make sure it's ok
git status
git diff
#now go ahead with commit
git commit -a -m "same|new message"
#eventually push tu remote
git push
David Hrbáč
la source
2

Dans cette situation, je git add -p(interactif), git commit -m blahpuis ranger ce qui reste si nécessaire.

J0hnG4lt
la source
2

Je ne sais pas comment le faire en ligne de commande, en utilisant uniquement SourceTree. Supposons que vous ayez modifié le fichier A et que vous ayez deux morceaux de modification dans le fichier B. Si vous souhaitez ne cacher que le deuxième morceau dans le fichier B et laisser tout le reste intact, procédez comme suit:

  1. Tout mettre en scène
  2. Apportez des modifications à votre copie de travail qui annulent toutes les modifications du fichier A. (par exemple, lancez l'outil de diff externe et faites correspondre les fichiers.)
  3. Faites en sorte que le fichier B ressemble à si seule une deuxième modification lui est appliquée. (par exemple, lancez l'outil de diff externe et annulez le premier changement.)
  4. Créez une cachette à l'aide de "Conserver les modifications par étapes".
  5. Décors tout
  6. Terminé!
Juozas Kontvainis
la source
2
git add .                           //stage all the files
git reset <pathToFileWillBeStashed> //unstage file which will be stashed
git stash                           //stash the file(s)
git reset .                         // unstage all staged files
git stash pop                       // unstash file(s)
celikz
la source
1
Eh bien, vous ne devriez pas faire ça. La réponse devrait fournir une solution à la question. Vous pouvez simplement poser votre propre question.
L_J
cette solution est l'une des réponses les plus simples à cette question. lisez la question, comparez toutes les réponses et la mienne alors si vous avez le moindre doute que cette réponse n'est ni une solution applicable ni des informations insuffisantes sur la question, alors nous pouvons reparler.
celikz
Cela ne fonctionnera pas, car la troisième commande, "git stash" n'honorera pas les fichiers intermédiaires. Les fichiers intermédiaires et non intermédiaires iront à la cachette. La question demande spécifiquement comment cacher un seul fichier
CyberProdigy
0

Une façon compliquée serait de tout d'abord commettre:

git add -u
git commit // creates commit with sha-1 A

Réinitialisez le commit d'origine mais récupérez le_one_file du nouveau commit:

git reset --hard HEAD^
git checkout A path/to/the_one_file

Maintenant, vous pouvez cacher le_one_file:

git stash

Nettoyage en enregistrant le contenu validé dans votre système de fichiers tout en réinitialisant le commit d'origine:

git reset --hard A
git reset --soft HEAD^

Ouais, un peu maladroit ...

Martin G
la source
0

Je n'ai trouvé aucune réponse à ce dont j'avais besoin et c'est aussi simple que:

git add -A
git reset HEAD fileThatYouWantToStash
git commit -m "committing all but one file"
git stash

Cela cache exactement un fichier.

SCBuergel.eth
la source
0

Réponse rapide


Pour rétablir un fichier modifié spécifique dans git, vous pouvez faire la ligne suivante:

git checkout <branch-name> -- <file-path>

Voici un exemple réel:

git checkout master -- battery_monitoring/msg_passing.py

Benyamin Jafari
la source
0

Si vous voulez cacher des fichiers modifiés, simplement

Ajoutez les fichiers que vous ne voulez pas cacher, dans Stage , puis exécutezgit stash save --keep-index

Il stockera tous les fichiers modifiés non mis en scène

Amin Shojaei
la source