Comment puis-je cacher un seul des multiples fichiers modifiés sur ma branche?
git diff -- *filename* > ~/patch
puis git checkout -- *filename*
et plus tard, vous pouvez git apply ~/patch
git stash push [--] [<pathspec>...]
.
Comment puis-je cacher un seul des multiples fichiers modifiés sur ma branche?
git diff -- *filename* > ~/patch
puis git checkout -- *filename*
et plus tard, vous pouvez git apply ~/patch
git stash push [--] [<pathspec>...]
.
Réponses:
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 add
ce 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:
git rebase -i <last good commit>
edit
.git reset HEAD^
git add <files you want to keep in this change>
git stash --keep-index
git add
les modifications.git commit
git stash pop
git rebase --continue
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).
git stash -p
est exactement ce que je cherchais. Je me demande si ce commutateur n'a été ajouté que récemment.
git stash --keep-index
est cassé. Si vous apportez plus de modifications, essayez git stash pop
ensuite 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.
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
stash -p
. J'attribue cette réponse car elle reste la plus interactive / conviviale.
git stash save -p my stash message
:; puisque l'ordre de l'argumenst n'est pas très intuitif ...
git log -p
, je pense que le -p
drapeau doit signifier "fais la chose cool que je veux mais je ne sais pas comment l'exprimer".
É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
pathspec
est 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 --patch
solution 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 --patch
pourrait 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 --patch
cela ne fonctionne pas, un processus manuel peut:
Pour un ou plusieurs fichiers, une solution intermédiaire serait de:
git stash
git stash
# cette fois, seuls les fichiers que vous souhaitez sont cachésgit stash pop stash@{1}
# réappliquez toutes vos modifications de fichiersgit 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.
git reset
(mixte)
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.
Quand git stash -p
(ou git add -p
avec stash --keep-index
) serait trop encombrant, je l'ai trouvé plus facile à utiliser diff
, checkout
et 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
git add -p
j'ai mentionnée dans ma propre réponse ci-dessus. +1.
git diff > file.diff
et git apply
sont mes outils habituels stash partiels. Je devrais peut-être envisager de passer à git stash -p
des ensembles de modifications plus importants.
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é.
../../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.
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.
git stash push
dé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 .
git stash apply
pour récupérer les modifications cachées?
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.
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 -p
mode 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).
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-index
quelque 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.
pushd
place cd
et 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.
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+
É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.
Vous pouvez simplement faire ceci:
git stash push "filename"
ou avec un message optionnel
git stash push -m "Some message" "filename"
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.txt
ou 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
}
}
}
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 stash
juste une alternative plus rapide et simple à la ramification et à la réalisation de tâches.
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:
checkout -f
n'est pas nécessaire, checkout
(sans -f
) suffit, j'ai mis à jour la réponse.
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 pop
peut être éliminé, vous pouvez reporter toutes vos modifications à la master
succursale 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 ...
Cela peut être fait facilement en 3 étapes en utilisant SourceTree.
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.
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.
git stash -p
vous permet de cacher un fichier entier rapidement et de quitter ensuite.
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.
git apply
n'ai aucune erreur mais que les changements ne sont pas non plus rapportés
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 suivisgit stash -k (--keep-index)
: stockez tous les fichiers suivis / non suivis et conservez-les dans le répertoire de travailgit stash -u (--include-untracked)
: cache tous les fichiers suivis / non suivisgit stash -p (--patch) -u (--include-untracked)
: commande non valideActuellement, la méthode la plus raisonnable pour pouvoir stocker des fichiers spécifiques suivis / non suivis consiste à:
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 .
Changements locaux:
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é.
Vous pouvez utiliser git status entre les étapes pour voir ce qui se passe.
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
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.
push
comme dansgit stash push --patch [file]
push
ne fonctionne que dans les versions plus récentes de Git, autrefois save
. Dans les deux cas push
ou save
sont implicites en appelant stash
: "Appeler git stash sans aucun argument équivaut à git stash push", docs
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
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:
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)
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 ...
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.
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
Si vous voulez cacher des fichiers modifiés, simplement
Ajoutez les fichiers que vous ne voulez pas cacher, dans Stage , puis exécutez
git stash save --keep-index
Il stockera tous les fichiers modifiés non mis en scène
git stash --keep-index
conserve l'index, mais il cache tout - à la fois dans l'index et à l'extérieur.