web-dev-qa-db-fra.com

git stash blunder: git stash pop et s'est soldé par des conflits de fusion

J'ai fait un git stash pop et j'ai eu des conflits de fusion. J'ai supprimé les fichiers du système de fichiers et procédé à un git checkout comme indiqué ci-dessous, mais les fichiers ne sont toujours pas fusionnés. J'ai ensuite essayé de remplacer les fichiers et de refaire un git checkout et le même résultat. J'ai éventuellement essayé de le forcer avec le drapeau -f. Toute aide serait appréciée!

chirag-patels-macbook-pro:haloror patelc75$ git status
app/views/layouts/_choose_patient.html.erb: needs merge
app/views/layouts/_links.html.erb: needs merge
# On branch prod-temp
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   db/schema.rb
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       unmerged:   app/views/layouts/_choose_patient.html.erb
#       unmerged:   app/views/layouts/_links.html.erb

chirag-patels-macbook-pro:haloror patelc75$ git checkout app/views/layouts/_choose_patient.html.erb
error: path 'app/views/layouts/_choose_patient.html.erb' is unmerged
chirag-patels-macbook-pro:haloror patelc75$ git checkout -f app/views/layouts/_choose_patient.html.erb
warning: path 'app/views/layouts/_choose_patient.html.erb' is unmerged
197
Chirag Patel

Voir man git merge ( COMMENT RESOUDRE LES CONFLITS ):

Après avoir vu un conflit, vous pouvez faire deux choses:

  • Décidez de ne pas fusionner. Les seuls nettoyages dont vous avez besoin sont de réinitialiser le fichier d'index sur le HEAD commit to reverse reverse 2. et de nettoyer les modifications apportées à l'arbre de travail effectuées par 2. et 3 .; git-reset --hard peut être utilisé pour cela.

  • Résoudre les conflits. Git marquera les conflits dans l’arbre de travail. Éditez les fichiers en forme et ajoutez-les à l’index. Utilisez git commit pour sceller l’accord.

Et sous TRUE MERGE (pour voir en quoi 2. et 3. se réfère):

Lorsqu'il n'est pas évident de savoir comment réconcilier les modifications, les événements suivants se produisent:

  1. Le pointeur HEAD reste le même.

  2. La référence MERGE_HEAD est définie pour pointer sur l'autre tête de branche.

  3. Les chemins qui ont fusionné proprement sont mis à jour à la fois dans le fichier d'index et dans votre arbre de travail.

  4. ...

Donc: utilisez git reset --hard si vous souhaitez supprimer les modifications de masquage de votre arborescence de travail, ou git reset si vous souhaitez simplement nettoyer l'index et laisser les conflits de votre arborescence de travail se fusionner à la main.

Sous man git stash (( OPTIONS, pop ), vous pouvez lire en plus:

L'application de l'état peut échouer avec des conflits; dans ce cas, il n'est pas supprimé de la liste de dissimulation. Vous devez résoudre les conflits manuellement et appeler ensuite git stash drop manuellement.

218
tanascius

J'ai eu une chose semblable à moi. Je ne voulais pas mettre en scène les fichiers pour l'instant, alors je les ai ajoutés avec git add puis juste git reset. Fondamentalement, cela a simplement ajouté et modifié mes modifications, mais a effacé les chemins non fusionnés.

41
Aaron

Si, comme moi, vous souhaitez généralement écraser le contenu du répertoire de travail avec celui des fichiers stockés et que le conflit persiste, vous devez résoudre le conflit à l'aide de git checkout --theirs -- . à la racine. .

Ensuite, vous pouvez git reset apporter toutes les modifications de l'index au répertoire de travail, car apparemment, en cas de conflit, les modifications apportées aux fichiers non en conflit restent dans l'index.

Vous pouvez également vouloir exécuter git stash drop [<stash name>] par la suite, pour vous débarrasser de la réserve, car git stash pop ne le supprime pas en cas de conflit.

12
Pedro Gimeno

Notez que Git 2.5 (T2 2015) un futur Git pourrait essayer de rendre ce scénario impossible.

Voir commit ed178ef par Jeff King (peff), 22 avril 2015.
(Fusion par Junio ​​C Hamano - gitster - in commit 05c3967 , 19 mai 2015)

Remarque: Ceci a été annulé. Voir ci-dessous .

stash: nécessite un index vierge à appliquer/pop

Problème

Si vous avez mis en scène le contenu dans votre index et exécutez "stash apply/pop", nous pouvons rencontrer un conflit et ajouter de nouvelles entrées à l'index.
La restauration de votre état d'origine est difficile à ce stade, car des outils tels que "git reset --keep" feront disparaître tout ce qui a été organisé .

En d'autres termes:

"git stash pop/apply" a oublié de s’assurer que non seulement l’arbre de travail est propre, mais aussi l’index.
Ce dernier point est important, car une application secrète peut être en conflit et l’index sera utilisé pour la résolution du conflit.

Solution

Nous pouvons rendre cela plus sûr en refusant de postuler quand des changements sont mis en scène.

Cela signifie que s'il y avait déjà eu des fusions en raison de l'application d'une cachette sur des fichiers modifiés (ajoutés mais non validés), il ne s'agirait plus de fusions, car la dissimulation apply/pop s'arrêterait immédiatement avec:

Cannot apply stash: Your index contains uncommitted changes.

Vous obliger à valider les modifications signifie que, en cas de fusion, vous pouvez facilement restaurer l'état initial (avant git stash apply/pop) avec un git reset --hard.


Voir commit 193761 (15 juin 2015), et commit ed178ef (22 avril 2015) par Jeff King (peff) .
(Fusion par Junio ​​C Hamano - gitster - dans commit bfb539b , 24 juin 2015)

Cette validation visait à améliorer la sécurité de l'application d'une cachette, car le processus d'application peut créer des entrées d'index conflictuelles, après lesquelles il est difficile de restaurer l'état d'index d'origine.

Malheureusement, certains workflows courants autour de "git stash -k", tels que:

git add -p       ;# (1) stage set of proposed changes
git stash -k     ;# (2) get rid of everything else
make test        ;# (3) make sure proposal is reasonable
git stash apply  ;# (4) restore original working tree

Si vous "git commit" entre les étapes (3) et (4), alors cela fonctionne. Toutefois, si ces étapes font partie d'un hook de pré-validation, vous n'avez pas cette opportunité (vous devez restaurer l'état d'origine, que les tests aient réussi ou non).

2
VonC