Question Stash seulement un fichier sur plusieurs fichiers qui ont changé avec Git?


Comment puis-je stocker uniquement un des multiples fichiers modifiés sur ma branche?


2437
2018-06-14 20:52


origine


Réponses:


Attention

Comme indiqué dans les commentaires, cela met tout dans la cachette, à la fois mise en scène et non mise en scène. L'index --keep-laisse juste l'index seul après que la cachette est faite. Cela peut entraîner des conflits de fusion lorsque vous affichez le cache ultérieurement.


Cela va stocker tout ce que vous n'avez pas déjà ajouté. Juste git add les choses 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. Fixer les choses au besoin. Ne pas oublier de git add tout changement.
  7. git commit
  8. git stash pop
  9. Répétez, à partir de # 5, si nécessaire.
  10. git rebase --continue

1216
2017-11-30 21:28



Vous pouvez aussi utiliser git stash save -p "my commit message". De cette façon, vous pouvez sélectionner quels morceaux doivent être ajoutés à la mémoire, 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

2612
2017-07-31 11:59



Puisque git est fondamentalement sur la gestion d'un dépôt entier contenu et index (et pas un ou plusieurs fichiers), git stash offres, sans surprise, avec le répertoire de travail.

En fait, depuis Git 2.13 (Q2 2017), vous pouvez stocker des fichiers individuels, avec:

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

Voir "Stash modifie des fichiers spécifiques" pour plus.


La réponse originale (ci-dessous, juin 2010) consistait à sélectionner manuellement ce que vous voulez cacher.

Casebash commentaires:

Ceci (le stash --patch solution originale) est sympa, mais j'ai souvent modifié beaucoup de fichiers donc l'utilisation de patch est ennuyante

bukzorde répondre (upvoted, novembre 2011) suggère une solution plus pratique, basée sur
git add + git stash --keep-index.
Allez voir et upvote sa réponse, qui devrait être officielle (au lieu de la mienne).

A propos de cette option, chhh signale un flux de travail alternatif dans les commentaires:

vous devriez "git reset --soft"après une telle cachette pour obtenir votre mise en scène claire:
  Afin d'obtenir l'état d'origine - qui est une zone de mise en scène claire et avec seulement quelques modifications non-mises en scène sélectionnées, on pourrait doucement réinitialiser l'index pour obtenir (sans commettre quelque chose comme vous - bukzor - fait).


(Réponse originale juin 2010: cachette manuelle)

Encore, git stash save --patch pourrait vous permettre d'atteindre la cachette partielle que vous recherchez:

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

Cependant, cela sauvegardera l'index complet (ce qui n'est peut-être pas ce que vous voulez, car il pourrait inclure d'autres fichiers déjà indexés), et un workstree partiel (qui pourrait ressembler à celui que vous voulez stocker).

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

pourrait être un meilleur ajustement.


Si --patchne fonctionne pas, un processus manuel pourrait:

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

  • copiez-les en dehors du repo Git
    (Réellement, Eleotlecram propose un alternative intéressante)
  • git stash
  • recopiez-les
  • git stash # cette fois, seuls les fichiers que vous voulez sont cachés
  • git stash pop stash@{1} # re-appliquer toutes les modifications de vos fichiers
  • git checkout -- afile # réinitialise le fichier au contenu HEAD, avant toute modification locale

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


237
2018-06-14 21:23



Quand git stash -p (ou git add -p avec stash --keep-index) serait trop lourd, je l'ai trouvé plus facile à utiliser diff, checkout et apply:

Pour "stocker" 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

76
2018-02-12 13:44



Disons que vous avez 3 fichiers

a.rb
b.rb
c.rb

et vous voulez stocker uniquement 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.


43
2017-10-31 07:10



Utilisation git stash push, comme ça:

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

Par exemple:

git stash push -- my/file.sh

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


33
2017-08-15 13:10



Une autre façon de faire ceci:

# 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 suis venu avec cela après (encore une fois) est venu à cette page et n'a pas aimé les deux premières réponses (la première réponse ne répond tout simplement pas à la question et je n'ai pas aimé travailler avec le -p mode interactif).

L'idée est la même que celle suggérée par @VonC en utilisant des fichiers en dehors du référentiel, vous sauvegardez les changements que vous voulez quelque part, supprimez les changements que vous ne voulez pas dans votre cachette, puis réappliquez les changements que vous avez supprimés. Cependant, j'ai utilisé la cachette git comme "quelque part" (et par conséquent, il y a une étape supplémentaire à la fin: enlever les cahnges que vous avez mis dans la cachette, parce que vous les avez également déplacés).


25
2018-02-05 10:16



Mise à jour (14/02/2015) - J'ai réécrit le script un peu, pour mieux gérer le cas des conflits, qui devraient maintenant être présentés comme des conflits non fusionnés plutôt que comme 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 quelques changements, et puis cacher seulement ces changements mis en scène.

Malheureusement, git n'offre pas de git stash --only-index ou similaire, alors j'ai créé 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 sauvegarder le script ci-dessus git-stash-index quelque part sur votre chemin, et peut ensuite l'invoquer comme git stash-index

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

Maintenant, le stash contient une nouvelle entrée qui contient seulement les changements que vous avez mis en scène, et votre arbre de travail contient toujours des changements non-statiques.

Dans certains cas, les modifications de l'arborescence de travail peuvent dépendre des modifications de l'index. Par conséquent, lorsque vous modifiez les modifications de l'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.


22
2018-06-16 21:00