git stash -> fusionner les modifications cachées avec les modifications actuelles


187

J'ai apporté quelques modifications à ma branche et j'ai réalisé que j'avais oublié que j'avais caché d'autres modifications nécessaires dans ladite branche. Ce que je veux, c'est un moyen de fusionner mes modifications cachées avec les modifications actuelles.

Y a-t-il un moyen de faire cela?

C'est plus pour plus de commodité, j'ai finalement abandonné et commis d'abord mes modifications actuelles, puis mes modifications cachées, mais j'aurais préféré les intégrer d'un seul coup.


Probablement en double de stackoverflow.com/q/1360712/72178
ks1322

La réponse de Joshua devrait être la réponse acceptée. Cet article de stackoverflow est le premier lien google pour cette question, donnez la bonne réponse à Internet!
Jérôme

Réponses:


272

Je viens de découvrir que si vos modifications non validées sont ajoutées à l'index (c'est-à-dire "mises en scène", en utilisant git add ...), alors git stash apply(et, vraisemblablement, git stash pop) feront réellement une fusion appropriée. S'il n'y a pas de conflits, vous êtes en or. Sinon, résolvez-les comme d'habitude avec git mergetoolou manuellement avec un éditeur.

Pour être clair, voici le processus dont je parle:

mkdir test-repo && cd test-repo && git init
echo test > test.txt
git add test.txt && git commit -m "Initial version"

# here's the interesting part:

# make a local change and stash it:
echo test2 > test.txt
git stash

# make a different local change:
echo test3 > test.txt

# try to apply the previous changes:
git stash apply
# git complains "Cannot apply to a dirty working tree, please stage your changes"

# add "test3" changes to the index, then re-try the stash:
git add test.txt
git stash apply
# git says: "Auto-merging test.txt"
# git says: "CONFLICT (content): Merge conflict in test.txt"

... qui est probablement ce que vous recherchez.


tl; dr

Exécutez d' git addabord.


8
Un tel hack, mais bon, cela fonctionne et semble être le seul moyen de le faire. J'aimerais qu'il y en ait eu git stash apply --forceou quelque chose.
Matt Kantor

13
En fait, ce n'est pas un hack - c'est une amélioration par rapport à ce que vous voulez, car vous pouvez facilement revenir aux modifications de l'index.
hoffmanc

2
Wow, ce comportement est-il vraiment voulu par git?
edi9999

9
Je ne pense pas qu'il y ait quelque chose qui ait jamais été «voulu» par git. Mon intuition est maintenant que tout ce qui est git le fait par hasard.
Profpatsch

5
C'est la solution parfaite. Je viens de le faire git add ., git stash applypuis git resetd'appliquer la réserve à mes modifications de travail et de fusionner sans avoir à faire de commits.
Stephen Smith

70

Exécution git stash popou git stash applyest essentiellement une fusion. Vous n'auriez pas dû avoir besoin de valider vos modifications actuelles à moins que les fichiers modifiés dans la réserve ne soient également modifiés dans la copie de travail, auquel cas vous auriez vu ce message d'erreur:

error: Your local changes to the following files would be overwritten by merge:
       file.txt
Please, commit your changes or stash them before you can merge.
Aborting

Dans ce cas, vous ne pouvez pas appliquer la réserve à vos modifications actuelles en une seule étape. Vous pouvez valider les modifications, appliquer le stash, valider à nouveau et écraser ces deux validations en utilisant git rebasesi vous ne voulez vraiment pas deux validations, mais cela peut être plus problématique que cela en vaut la peine.


1
J'ai reçu ce message - les modifications ne sont pas en conflit mais partagent les mêmes fichiers, en utilisant des stashes / apply?
Bemis

1
Désolé, c'est ce que je voulais dire par "fusionner les conflits", mais c'était un mauvais choix de mots. Je pense que ce message d'erreur est assez définitif: si les fichiers modifiés dans la copie de travail sont également modifiés dans la cachette, vous ne pouvez pas appliquer la cachette. J'ai mis à jour ma réponse avec une solution de contournement possible.
Brandan

3
Je ne considérerais pas cela comme une réponse dans tous les cas. Vous n'avez peut-être caché qu'une partie d'un ensemble de modifications dans un fichier spécifique parce que vous vouliez tester quelque chose pendant le développement. Et vous ne voudrez peut-être pas valider le contenu actuel du fichier à ce stade (ou pas du tout) car c'est WIP. C'est un vrai problème avec git que les modifications cachées ne peuvent pas être fusionnées dans votre branche actuelle
Thomas Watson

21
La réponse de Joshua Warner devrait être celle marquée comme correcte. Pour fusionner une réserve, mettez en scène vos modifications, appliquez la réserve, gérez les conflits, puis (si vous le souhaitez) annulez vos modifications.
Vroo

4
"Vous pouvez valider les modifications, appliquer le stash, valider à nouveau et écraser ces deux validations en utilisant git rebase si vous ne voulez vraiment pas deux validations, mais cela peut être plus de problèmes que cela en vaut la peine." Au lieu de cela, vous pouvez faire: Valider les modifications, appliquer la réserve, puis git commit --amend.
gabe

27

Ce que je veux, c'est un moyen de fusionner mes modifications cachées avec les modifications actuelles

Voici une autre option pour le faire:

git stash show -p|git apply
git stash drop

git stash show -paffichera le patch de la dernière réserve sauvegardée. git applyl'appliquera. Une fois la fusion terminée, la réserve fusionnée peut être supprimée avec git stash drop.


1
Merci pour cela - je ne sais pas pourquoi git stash popne pas faire cela dans les cas où la fusion s'applique proprement ...
Iguananaut

Version étendue: git stash show -p --no-color | git apply --3way( --3way= revenir sur la fusion à 3 voies si le correctif échoue).
DmitrySandalov

Mais git stash show -pcrée une différence entre le contenu caché et le commit lors de la création initiale de l'entrée cachée . Cela écraserait donc les modifications du fichier de travail effectuées par l'OP.
Paul

Pourquoi écraser? Le diff produit avec git stash show -psera fusionné par git apply, s'il est possible de se passer de conflits.
ks1322 le

1

La façon dont je fais cela est donc d' git addabord de le faire git stash apply <stash code>. C'est le moyen le plus simple.


4
Comment n'est-ce pas une copie exacte du tl; dr de la réponse acceptée?
RomainValeri

0

Comme suggéré par @Brandan, voici ce que je devais faire pour me déplacer

error: Your local changes to the following files would be overwritten by merge:
       file.txt
Please, commit your changes or stash them before you can merge.
Aborting

Suivez ce processus:

git status  # local changes to `file`
git stash list  # further changes to `file` we want to merge
git commit -m "WIP" file
git stash pop
git commit -m "WIP2" file
git rebase -i HEAD^^  # I always use interactive rebase -- I'm sure you could do this in a single command with the simplicity of this process -- basically squash HEAD into HEAD^
# mark the second commit to squash into the first using your EDITOR
git reset HEAD^

Et vous vous retrouverez avec des modifications locales entièrement fusionnées file, prêt à faire plus de travail / nettoyage ou à faire un seul bon commit. Ou, si vous savez que le contenu fusionné de filesera correct, vous pouvez écrire un message approprié et sauter git reset HEAD^.


0

Peut-être, ce n'est pas la pire des idées de fusionner (via difftool) depuis ... oui ... une branche!

> current_branch=$(git status | head -n1 | cut -d' ' -f3)
> stash_branch="$current_branch-stash-$(date +%yy%mm%dd-%Hh%M)"
> git stash branch $stash_branch
> git checkout $current_branch
> git difftool $stash_branch

0

tu peux facilement

  1. Validez vos modifications actuelles
  2. Libérez votre réserve et résolvez les conflits
  3. Valider les modifications depuis le cache
  4. Réinitialisation logicielle pour le commit dont vous venez (dernier commit correct)

-1

Une autre option est de faire un autre "git stash" des modifications locales non validées, puis de combiner les deux stashes git. Malheureusement, git ne semble pas avoir de moyen de combiner facilement deux cachettes. Donc, une option est de créer deux fichiers .diff et de les appliquer tous les deux - au moins ce n'est pas un commit supplémentaire et n'implique pas un processus en dix étapes: |

comment: https://stackoverflow.com/a/9658688/32453


Cela transforme le problème de l'application d'un diff en un problème d'application de deux diffs. De plus, la solution acceptée n'implique pas de commit, juste une étape, et ce n'est qu'une seule commande (git add). (Je ne suis pas le downvoter.)
Eike

Pour moi au moins, c'est plus simple, moins de magie vaudou ... bravo!
rogerdpack
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.