Ne stockez qu’un seul fichier parmi plusieurs fichiers modifiés avec Git?

Comment puis-je ne stocker qu’un seul des fichiers modifiés sur ma twig?

Attention

Comme noté dans les commentaires, cela met tout dans la réserve, à la fois mis en scène et non mis en scène. L’index –keep-laisse juste l’index seul après que le stash est fait. Cela peut provoquer des conflits de fusion lorsque vous placez le cache ultérieurement.


Cela cachera tout ce que vous n’avez pas encore ajouté. Juste git add les choses que vous voulez garder, puis lancez-le.

 git stash --keep-index 

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

  1. git rebase -i
  2. Marquer certains changements comme edit .
  3. git reset HEAD^
  4. git add
  5. git stash --keep-index
  6. Réparez les choses si nécessaire. N’oubliez pas d’y git add des modifications.
  7. git commit
  8. git stash pop
  9. Répétez, à partir de # 5, si nécessaire.
  10. git rebase --continue

Vous pouvez également utiliser git stash save -p "my commit message" . De cette façon, vous pouvez sélectionner les postes à append au cache, 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 

Comme git consiste fondamentalement à gérer un contenu et un index de tous les référentiels (et non un ou plusieurs fichiers), les offres de git stash , sans surprise, avec tout le répertoire de travail .

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

 git stash push [--] [...] 

Reportez-vous à la section ” Cacher les modifications apscopes à des fichiers spécifiques ” pour plus d’informations.


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

Commentaires de Casebash :

Ceci (la solution stash --patch original de stash --patch ) est sympa, mais souvent j’ai modifié beaucoup de fichiers donc utiliser le patch est agaçant

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

A propos de cette option, chhh indique un stream de travail alternatif dans les commentaires:

vous devriez ” git reset --soft ” après un tel git reset --soft pour récupérer votre mise en scène claire:
Pour arriver à l’état d’origine – qui est une zone de mise en scène claire et avec seulement quelques modifications non mises en scène, on pourrait réinitialiser doucement l’index pour obtenir (sans rien commettre comme vous – bukzor – did).


(Réponse originale juin 2010: cachette manuelle)

Pourtant, git stash save --patch pourrait vous permettre d’obtenir la réserve partielle suivante:

Avec --patch , vous pouvez sélectionner de manière interactive des hunks dans le diff entre HEAD et l’arbre de travail à ranger.
L’entrée stash est construite de telle sorte que son état d’index est identique à l’état d’index de votre référentiel, et son worktree ne contient que les modifications que vous avez sélectionnées de manière interactive. Les modifications sélectionnées sont alors annulées depuis votre worktree.

Cependant, cela sauvera l’index complet (qui peut ne pas correspondre à ce que vous voulez puisqu’il pourrait inclure d’autres fichiers déjà indexés), ainsi qu’un worktree partiel (qui pourrait ressembler à celui que vous souhaitez cacher).

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

pourrait être un meilleur ajustement.


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

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

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

À la fin de ce processus plutôt encombrant, vous n’avez qu’un ou plusieurs fichiers cachés.

Lorsque git stash -p (ou git add -p avec stash --keep-index ) serait trop encombrant, j’ai trouvé plus facile d’utiliser diff , checkout et d’ 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 

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.

Utilisez git stash push , comme ceci:

 git stash push [--] [...] 

Par exemple:

 git stash push -- my/file.sh 

Ceci est disponible depuis Git 2.13, publié au spring 2017.

Une autre façon de faire cela:

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

L’idée est la même que celle suggérée par @VonC pour utiliser des fichiers en dehors du référentiel, vous enregistrez les modifications souhaitées, supprimez les modifications inutiles dans votre réserve, puis réappliquez les modifications apscopes. Cependant, j’ai utilisé le git stash comme “quelque part” (et par conséquent, il y a une étape supplémentaire à la fin: supprimer les modifications que vous avez apscopes dans le cache, car vous les avez également déplacées).

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


Je trouve souvent plus intuitif de faire l’inverse de l’approche de @ bukzor. C’est-à-dire pour mettre en place des modifications, puis ne conserver que les modifications par étapes.

Malheureusement, git n’offre pas de git stash – uniquement sur 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 enregistrer le script ci-dessus en tant que git-stash-index quelque part sur votre chemin, puis l’invoquer en tant que git stash-index

 #  git add  git stash-index 

À présent, le stash contient une nouvelle entrée qui contient uniquement les modifications que vous avez effectuées, et votre arborescence de travail contient toujours des modifications non planifiées.

Dans certains cas, les modifications apscopes à l’arborescence de travail peuvent dépendre des modifications d’index. Par conséquent, lorsque vous modifiez les index, les modifications apscopes à l’arborescence de travail génèrent un conflit. Dans ce cas, vous obtiendrez les conflits non fusionnés que vous pouvez résoudre avec git merge / git mergetool / etc.

Puisque créer des twigs dans Git est sortingvial, vous pouvez simplement créer une twig temporaire et y vérifier les fichiers individuels.

Juste au cas où vous voudriez réellement dire que vous voulez supprimer les changements à chaque fois que vous utilisez git stash (et que vous n’utilisez pas vraiment git stash pour le cacher temporairement), vous pouvez alors utiliser

 git checkout --  

[ NOTE ]

Ce git stash est juste une alternative simple et rapide à la création de twigs.

Enregistrez le code suivant dans un fichier, par exemple, nommé stash . L’utilisation est stash . L’argument est l’expression régulière du chemin complet du fichier. Par exemple, pour cacher un / b / c.txt, cachez 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,ssortingng) } "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 } } } 

Le problème avec la solution «intermédiaire» de VonC pour copier des fichiers en dehors du repository Git est que vous perdez les informations de chemin, ce qui rend la copie de fichiers plus tard un peu compliquée.

Il est plus facile d’utiliser tar (des outils similaires le feront probablement) au lieu de copier:

  • tar cvf /tmp/stash.tar chemin / vers / certains / chemin du fichier / vers / certains / autre / fichier (… etc.)
  • Chemin de vérification de git / vers / un / chemin de fichier / vers / certains / autre / fichier
  • git stash
  • tar xvf /tmp/stash.tar
  • etc. (voir la suggestion «intermédiaire» de VonC)

Cela peut se faire facilement en 3 étapes en utilisant SourceTree.

  1. Commence temporairement tout ce que tu ne veux pas cacher.
  2. Git ajoute tout le rest, puis range-le.
  3. Pop votre validation temporaire en exécutant git reset, ciblant la validation avant votre version temporaire.

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 append. Une fois ajouté, il suffit de les engager dans un commit temporaire. Cliquez ensuite sur la case à cocher pour append toutes les modifications, puis cliquez sur stash pour tout ranger. Avec les modifications cachées, jetez un coup d’œil à votre liste de validations et notez le hash pour le commit avant votre validation temporaire, puis lancez ‘git reset hash_b4_temp_commit’, qui revient à “sauter” le commit en réinitialisant votre twig au commettre juste avant Maintenant, il ne vous rest plus que ce que vous ne voulez pas cacher.

Parfois, j’ai fait un changement sans rapport sur ma twig avant de le commettre, et je veux le déplacer dans une autre twig et la valider séparément (comme master). Je fais ça:

 git stash git checkout master git stash pop git add  git commit -m 'Minor feature' git stash git checkout topic1 git stash pop ...... 

Notez que le premier stash peut être éliminé, vous pouvez transférer tous vos changements dans la twig principale lorsque vous passez à la caisse, mais seulement s’il n’y a pas de conflit. Aussi, si vous créez une nouvelle twig pour les modifications partielles, vous aurez besoin de la cachette.

Vous pouvez le simplifier en supposant aucun conflit et aucune nouvelle twig:

 git checkout master git add  git commit -m 'Minor feature' git checkout topic1 ...... 

Stash même pas nécessaire …

Chaque réponse ici est si compliquée …

Qu’en est-il de “stash”:

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

Ceci pour faire revenir le fichier:

 git apply /tmp/stash.patch 

Exactement le même comportement que de cacher un fichier et de le rentrer.

J’utiliserais git stash save --patch . Je ne trouve pas l’interactivité agaçante car il existe des options pour appliquer l’opération souhaitée à des fichiers entiers.

J’ai examiné les réponses et les commentaires à ce sujet et un certain nombre de sujets similaires. Sachez qu’aucune des commandes suivantes n’est correcte pour pouvoir stocker des fichiers suivis / non suivis spécifiques :

  • git stash -p (--patch) : sélectionne les hunks manuellement, à l’exclusion des fichiers non suivis
  • git stash -k (--keep-index) : stocke tous les fichiers suivis / non suivis et les garde dans le répertoire de travail
  • git stash -u (--include-untracked) : git stash -u (--include-untracked) 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 suivis / non suivis consiste à:

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

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

Solution

Changements locaux:

  • fichier_A (modifié) non mis en scène
  • fichier_B (modifié) non mis en scène
  • fichier_C (modifié) non mis en scène

Pour créer un cache “my_stash” avec uniquement 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. append le fichier_C à la zone de transit
  2. créer un stash temporaire nommé “temp_stash” et conserver les modifications sur file_C
  3. créer la cachette voulue (“my_stash”) avec uniquement les modifications sur file_C
  4. appliquer les modifications dans “temp_stash” (fichier_A et fichier_B) sur votre code local et supprimer le cache

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

Dans cette situation, je vais git add -p (interactif), git commit -m blah et ensuite ranger ce qui rest si nécessaire.

git add . //stage all the files git reset //unstage file which will be stashed git stash //stash the file git reset . // unstage all staged files

Situation similaire. A commis et réalisé que ce n’est pas correct.

 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, uniquement en utilisant SourceTree. Disons que vous avez modifié le fichier A et que vous avez deux changements de fichiers dans le fichier B. Si vous souhaitez ne conserver que le deuxième morceau du fichier B et ne pas toucher à d’autres éléments, procédez comme suit:

  1. Tout mettre en scène
  2. Apportez des modifications à votre copie de travail pour annuler toutes les modifications apscopes au fichier A. (par exemple, lancer l’outil de diff externe et faire correspondre les fichiers).
  3. Faites en sorte que le fichier B ressemble à un deuxième changement. (par exemple, lancer l’outil de diff externe et annuler le premier changement).
  4. Créez une réserve en utilisant “Conserver les modifications par étapes”.
  5. Tout décoller
  6. Terminé!

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

Essayez d’append les fichiers en utilisant ” git add filepath “.

Plus tard, exécutez cette ligne

git stash --keep-index

Réponse rapide


Pour annuler un fichier modifié spécifique dans git, vous pouvez effectuer la ligne suivante:

 git checkout  --  

Voici un exemple concret:

 git checkout master -- battery_monitoring/msg_passing.py 

Une manière compliquée serait de tout d’abord commettre:

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

Revenir à la validation d’origine mais extraire le fichier_one de la nouvelle validation:

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

Vous pouvez maintenant ranger le fichier_one_file:

 git stash 

Nettoyage en enregistrant le contenu engagé dans votre système de fichiers tout en rétablissant la validation 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.