J'ai sauté une cachette et il y avait un conflit de fusion. Contrairement à la question qui est répertoriée en tant que duplicata, j'avais déjà quelques modifications non validées dans le répertoire que je voulais conserver. Je ne veux pas seulement faire disparaître le conflit de fusion, mais aussi remettre mon répertoire dans l'état où il se trouvait avant la sortie.
J'ai essayé git merge --abort
, mais git a affirmé qu'aucune fusion n'était en cours. Existe-t-il un moyen simple d’abandonner un pop sans détruire les modifications que j’avais apportées au répertoire à l’origine?
Ok, je pense avoir travaillé sur "Git Stash Unapply". C'est plus complexe que git apply --reverse
car vous avez besoin d'une action de fusion inverse au cas où la fusion aurait été effectuée par git stash apply
.
La fusion inverse nécessite que toutes les modifications actuelles soient insérées dans l'index:
git add -u
Puis inversez le merge-recursive
qui a été effectué par git stash apply
:
git merge-recursive stash@{0}: -- $(git write-tree) stash@{0}^1
Maintenant, il ne vous restera plus que les changements non stash. Ils seront dans l'index. Vous pouvez utiliser git reset
pour annuler vos modifications si vous le souhaitez.
Étant donné que votre git stash apply
original a échoué, je suppose que l'inverse peut également échouer car certaines des choses qu'il souhaite annuler ne sont pas terminées.
Voici un exemple montrant comment la copie de travail (via git status
) est nettoyée à nouveau:
$ git status
# On branch trunk
nothing to commit (working directory clean)
$ git stash apply
Auto-merging foo.c
# On branch trunk
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: foo.c
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git add -u
$ git merge-recursive stash@{0}: -- $(git write-tree) stash@{0}^1
Auto-merging foo.c
$ git status
# On branch trunk
nothing to commit (working directory clean)
Mon cas d'utilisation: j'ai juste essayé de sauter sur la mauvaise branche et j'ai eu des conflits. Tout ce dont j'ai besoin, c'est d'annuler l'opération, mais de la conserver dans la liste de sélection afin de pouvoir la placer dans la branche appropriée. J'ai fait ça:
git reset HEAD --hard
git checkout my_correct_branch
git stash pop
Facile.
Edit: À partir de la documentation git help stash
dans la section pop:
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.
Si l'option --index est utilisée, tente de rétablir non seulement les modifications de l'arborescence de travail, mais également celles de l'index. Toutefois, cela peut échouer en cas de conflits (qui sont stockés dans l'index et où vous ne pouvez donc plus appliquer les modifications telles qu'elles étaient à l'origine).
Essayez de copier en dur tout votre rapport dans un nouveau répertoire (pour en avoir une copie) et exécutez:
git stash show
et sauvegardez cette sortie quelque part si vous en tenez à vous.
then: git stash drop
pour supprimer le cache en conflit, puis: git reset HEAD
Cela devrait laisser votre pension dans l'état où elle était avant (heureusement, je n'ai toujours pas été en mesure de vous reprocher votre problème)
===
J'essaie de reproduire votre problème, mais tout ce que je reçois quand on utilise git stash pop
est:
error: Your local changes to the following files would be overwritten by merge:
...
Please, commit your changes or stash them before you can merge.
Aborting
Dans un répertoire propre:
git init
echo hello world > a
git add a & git commit -m "a"
echo hallo welt >> a
echo hello world > b
git add b & git commit -m "b"
echo hallo welt >> b
git stash
echo hola mundo >> a
git stash pop
Je ne vois pas git qui essaye de fusionner mes modifications, ça échoue. Avez-vous des étapes de reprographie que nous pouvons suivre pour vous aider?
Si vous n'avez pas à vous soucier des autres modifications que vous avez apportées et que vous voulez simplement revenir au dernier commit, vous pouvez alors:
git reset .
git checkout .
git clean -f
OK, je pense avoir réussi à trouver un flux de travail qui vous ramènera à l'endroit où vous devez être (comme si vous n'aviez pas fait la pop).
PRENEZ UNE SAUVEGARDE AVANT LA MAIN !! Je ne sais pas si cela fonctionnera pour vous, alors copiez l'intégralité de votre pension au cas où cela ne fonctionnerait pas.
1) Corrigez les problèmes de fusion et résolvez tous les conflits en sélectionnant tous les changements apportés par le correctif (dans tortoisemerge, cela apparaît sous la forme one.REMOETE (le leur)).
git mergetool
2) Validez ces modifications (elles seront déjà ajoutées via la commande mergetool). Donnez-lui un message de "fusion" ou quelque chose dont vous vous souvenez.
git commit -m "merge"
3) Maintenant, vous aurez toujours vos modifications locales non mises en scène que vous avez commencées à l’origine, avec un nouveau commit à partir du patch (nous pourrons nous en débarrasser plus tard). Maintenant, commettez vos modifications non mises en scène
git add .
git add -u .
git commit -m "local changes"
4) Inverser le patch. Cela peut être fait avec la commande suivante:
git stash show -p | git apply -R
5) Commettez ces changements:
git commit -a -m "reversed patch"
6) Se débarrasser des commits patch/unpatch
git rebase -i HEAD^^^
à partir de là, supprimez les deux lignes contenant "fusion" et "patch inversé".
7) Récupérez vos modifications non liées et annulez la validation des modifications locales
git reset HEAD^
Je l'ai parcouru avec un exemple simple et cela vous ramène à l'endroit où vous voulez être - juste avant que la réserve ne soit ouverte, avec vos modifications locales et la réserve restant disponible.
J'ai résolu ceci d'une manière quelque peu différente. Voici ce qui s'est passé.
Tout d'abord, j'ai sauté sur la mauvaise branche et j'ai eu des conflits. La cachette est restée intacte mais l'index était en résolution de conflit, bloquant de nombreuses commandes.
Un simple git reset HEAD
a annulé la résolution du conflit et laissé les modifications non validées (et NON DÉSIRÉES).
Plusieurs git co <filename>
ont rétabli l'index à l'état initial. Finalement, j'ai changé de branche avec git co <branch-name>
et ai lancé un nouveau git stash pop
, qui a été résolu sans conflit.
Quelques idées:
Utilisez git mergetool
pour scinder les fichiers de fusion en pièces originales et nouvelles. Espérons que l’un de ceux-ci est le fichier avec vos modifications non stockées.
Appliquez le diff de la réserve à l'envers, pour annuler uniquement ces modifications. Vous devrez probablement séparer manuellement les fichiers avec les conflits de fusion (dans l’espoir que l’astuce ci-dessus fonctionnera).
Je n’ai testé ni l’un ni l’autre, donc je ne sais pas avec certitude qu’ils fonctionneront.
Je pourrais reproduire propre git stash pop
sur un répertoire "sale", avec des modifications non validées, mais pas encore pop qui génère un conflit de fusion.
Si lors du conflit de fusion, le stash que vous avez essayé d'appliquer n'a pas disparu, vous pouvez essayer d'examiner git show stash@{0}
(éventuellement avec --ours
ou --theirs
) et de le comparer à git statis
et git diff HEAD
. Vous devriez pouvoir voir quels changements ont été apportés par l’application d’une réserve.
Si DavidG a raison de dire qu'il n'a pas été masqué à cause du conflit de fusion, vous devez simplement nettoyer votre répertoire de travail. Rapidement git commit
tout ce qui compte pour vous. (Vous pouvez reset
ou squash
la validation plus tard si vous n’êtes pas encore terminé.) Puis, avec tout ce qui vous intéresse, git reset
tout ce que git stash pop
a déversé dans votre travail. annuaire.
Utilisez git reflog
pour répertorier toutes les modifications apportées à votre historique git. Copiez un identifiant d'action et tapez git reset ACTION_ID
S'il n'y a pas eu de changements programmés avant le git stash pop
, comme dans la question, les deux commandes suivantes devraient alors fonctionner.
git diff --name-only --cached | xargs git checkout --ours HEAD
git ls-tree stash@{0}^3 --name-only | xargs rm
La première inverse toute fusion de la réserve, réussie ou non. La seconde supprime tous les fichiers non suivis introduits par la cachette.
De man git stash
: The working directory must match the index.
que @DavidG souligne, le stash pop
échouera en cas de conflit entre des fichiers modifiés actuellement non mis en scène. En tant que tel, nous ne devrions pas avoir à nous soucier de la résolution des conflits de fusion au-delà du retour à HEAD
. Tous les fichiers modifiés restants sont alors sans lien avec la stash et ont été modifiés avant le stash pop
S'il y avait des changements mis en scène, je ne sais pas si nous pouvons utiliser les mêmes commandes et vous voudrez peut-être essayer la technique de @Ben Jackson. Suggestions appréciées ..
Voici une configuration de test pour tous les différents cas https://Gist.github.com/here/4f3af6dafdb4ca15e804
# Result:
# Merge succeeded in m (theirs)
# Conflict in b
# Unstaged in a
# Untracked in c and d
# Goal:
# Reverse changes to successful merge m
# Keep our version in merge conflict b
# Keep our unstaged a
# Keep our untracked d
# Delete stashed untracked c
Je poste ici en espérant que les autres trouveront ma réponse utile. J'ai eu un problème similaire lorsque j'ai essayé de créer une pop cachée sur une branche différente de celle que j'avais cachée. Dans mon cas, aucun fichier non engagé ni dans l'index, mais toujours dans le cas des conflits de fusion (même cas que @pid). Comme d'autres l'ont fait remarquer précédemment, la copie masquée git ayant échoué a bien conservé ma copie, puis une réinitialisation rapide de la touche *HEAD ainsi que le retour à ma branche d'origine et le stockage à partir de là ont résolu mon problème.