636 votes

Comment résoudre un conflit de stash git sans commit ?

Comme demandé dans cette question Je veux aussi savoir comment résoudre un conflit d'intérêts. git stash pop sans ajouter toutes les modifications à un commit (tout comme le fait "git stash pop" sans conflit).

Mon approche actuelle n'est pas très cool parce que je le fais de cette façon :

git stash pop  # -> CONFLICT
git stash drop
# [resolve conflict]
# [add conflict files]
git reset HEAD # <all files that are in commit-mode>

Comment se reproduire :

mkdir foo; cd foo; git init
echo "1" > one
echo "2" > two
git add -A; git commit -m "first"
echo "1.1" > one
echo "2.1" > two
git stash
echo "2.2" > two
git commit -a -m "second"
echo "Only this file would stay in HEAD without the conflict" > third
git add third
git stash pop
git status

2016-06-27 : Ajout d'un nouveau fichier appelé 'third' à l'exemple pour montrer que les solutions de contournement comme celle de scy ne fonctionnent que pour les HEADs vides mais ne règlent pas le problème initial qui est que le HEAD n'a pas le même contenu comme pour un HEAD. git stash pop sans conflit.

0 votes

Alors vous git add vos fichiers de conflit résolus, en les plaçant effectivement dans l'index, et vous voudriez ne pas les avoir dans notre index ?

0 votes

Oui, c'est vrai. Je veux juste le comportement qui git stash pop a lorsqu'il n'y a pas de conflit (mais avec notification des fichiers qui doivent être fusionnés).

2 votes

Il semble que la réponse à cette question soit ici : stackoverflow.com/questions/3945826/git-stash-questions . Dans la réponse choisie, au 4ème commentaire, Adam explique pourquoi git fait cela.

306voto

scy Points 2009

Supposons que vous ayez un scénario dans lequel vous cachez vos modifications afin de les tirer depuis l'origine. Peut-être parce que vos modifications locales sont juste debug: true dans un fichier de paramètres. Maintenant, vous tirez et quelqu'un a introduit un nouveau paramètre à cet endroit, créant un conflit.

git status dit :

# On branch master
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#   both modified:      src/js/globals.tpl.js
no changes added to commit (use "git add" and/or "git commit -a")

Ok. J'ai décidé de faire ce que Git a suggéré : j'ai résolu le conflit et je me suis engagé :

vim src/js/globals.tpl.js
# type type type …
git commit -a -m WIP   # (short for "work in progress")

Maintenant ma copie de travail est dans l'état que je veux, mais j'ai créé un commit que je ne veux pas avoir. Comment puis-je me débarrasser de ce commit sans modifier ma copie de travail ? Attendez, il y a une commande populaire pour cela !

git reset HEAD^

Ma copie de travail n'a pas été modifiée, mais le commit WIP a disparu. C'est exactement ce que je voulais ! (Notez que je n'utilise pas --soft ici, parce que s'il y a des fichiers fusionnés automatiquement dans votre cachette, ils sont mis à jour automatiquement et donc vous vous retrouveriez avec ces fichiers à nouveau mis à jour après reset .)

Mais il reste encore une chose : La page de manuel de git stash pop nous rappelle que " L'application de l'état peut échouer en cas de conflits ; dans ce cas, il n'est pas supprimé de la liste de la réserve. Vous devez résoudre les conflits à la main et appeler git stash drop manuellement après." C'est donc exactement ce que nous faisons maintenant :

git stash drop

Et c'est fait.

34 votes

Il y a juste beaucoup de laideur inhérente à devoir délibérément faire un commit reset HEAD^... pour quelque chose qui ne devrait affecter que l'arbre de travail.

8 votes

Pourquoi ne pas simplement résoudre les conflits et ensuite git add <resolved conflict files> suivi par git reset HEAD ?

0 votes

Merci pour la suggestion, mais cela ne résout pas le problème initial, à savoir que le comportement n'est pas le même que celui de l'entreprise. git stash pop sans conflit. Il suffit d'ajouter un autre fichier à HEAD avant de faire le conflit. git stash pop et que votre git commit -a -m WIP ajouterait également le nouveau fichier au commit. Mais sans conflit, seul le nouveau fichier resterait dans HEAD mais pas le fichier git stash pop des fichiers.

90voto

ComputerDruid Points 678

Au lieu d'ajouter les modifications que vous effectuez pour résoudre le conflit, vous pouvez utiliser la fonction git reset HEAD file pour résoudre le conflit sans mettre en scène vos changements.

Il se peut toutefois que vous deviez exécuter cette commande deux fois. Une fois pour marquer le conflit comme résolu et une fois pour annuler les changements qui ont été mis en scène par la routine de résolution de conflit.

Il est possible qu'il y ait un mode de réinitialisation qui fasse ces deux choses simultanément, bien qu'il n'y en ait pas actuellement.

2 votes

Le mode de réinitialisation est celui que je recherche - les autres solutions de contournement sont comme celle que j'ai décrite et ne sont pas pratiques pour plus de 5 fichiers.

25 votes

Et utilisez ensuite "git stash drop" pour terminer le "git stash pop".

2 votes

Bien que la question ne le demande pas explicitement, il pourrait être utile de mettre à jour la réponse pour inclure "git stash drop" car le stash n'est pas abandonné automatiquement dans le cas d'un conflit.

39voto

mr.musicman Points 732
git checkout stash -- .

a fonctionné pour moi.

Note cette méthode peut être dangereuse car elle n'essaie pas de fusionner les modifications de la cachette dans votre copie de travail. écrase avec les fichiers cachés à la place. Donc vous pouvez perdre vos modifications non validées.

0 votes

Cela a aidé lorsque "git pull --autostash" introduit des commits de fusion non désirés et git checkout stash -- . écrase inconditionnellement les conflits de stash.

0 votes

Cela m'a aidé à sortir de "l'enfer de git" où le même conflit continuait à se produire même après avoir suivi les suggestions de git. Je faisais git stash pop résoudre le conflit, git add/commit, et git stash pop produirait le même problème. Après avoir exécuté ce qui précède, j'ai pu exécuter git stash pop et ça a marché.

0 votes

Cela m'a aidé dans une situation où Github Actions build remplace les balises d'image Docker dans les manifestes Kubernetes et les pousse de la branche dev vers la branche staging. La création d'un PR pour fusionner la branche staging modifiée avec la branche principale provoquait des conflits et cette réponse m'a sauvé la mise.

6voto

Marco Ponti Points 235

Il semble que ce soit la réponse que vous cherchez. Je ne l'ai pas encore essayé personnellement, mais il semble que cela puisse faire l'affaire. Avec cette commande, GIT essaiera d'appliquer les changements tels qu'ils étaient auparavant, sans essayer de les ajouter tous pour le commit.

git stash apply --index

voici l'explication complète :

http://git-scm.com/book/en/Git-Tools-Stashing

0 votes

Merci pour cette astuce, mais cela ne servira à rien alors que j'ai déjà fait git stash pop - ou existe-t-il un moyen de revenir en arrière et de faire git stash apply --index quand j'ai découvert que git stash pop se heurtera à un conflit ?

0 votes

J'ai ajouté un exemple sur la façon de produire ceci - imaginez que vous éditez plus de 10 fichiers, et que vous ne savez pas lequel d'entre eux vous avez modifié en dehors de la cachette.

3 votes

Si vous regardez au bas de ce post ICI il est dit que si vous exécutez git stash pop et qu'elle se termine par des conflits, la réserve n'est pas supprimée... donc vous pouvez exécuter git reset --hard pour défaire le pop et ensuite essayer la solution que j'ai suggérée.

2voto

cherish Points 6

git stash branch qui crée une nouvelle branche pour vous, vérifie le commit sur lequel vous étiez lorsque vous avez caché votre travail. le commit sur lequel vous étiez quand vous avez caché votre travail, réapplique votre travail à cet endroit, et puis laisse tomber la cachette si l'application est réussie. check ce

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X