web-dev-qa-db-fra.com

Comment résoudre les conflits de cache git sans commit?

Comme demandé dans cette question , je veux aussi savoir comment résoudre un git stash pop en conflit sans ajouter toutes les modifications à un commit (tout comme "git stash pop" sans conflit).

Mon approche actuelle est très peu 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>

[Mise à jour] Une façon de le 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é "troisième" à l'exemple pour montrer que des solutions de contournement telles que la solution de scy fonctionnent uniquement pour les HEADs vides, mais ne résolvent pas le problème initial lié au HEAD ne t avoir le même contenu comme pour un git stash pop sans conflit.

429
Sven

Ne suivez pas les autres réponses

Eh bien, vous pouvez les suivre :). Mais je ne pense pas que le fait de valider, puis de redéfinir la branche pour supprimer ce commit, et que les solutions de contournement similaires proposées dans d'autres réponses constituent un moyen simple de résoudre ce problème.

Solution propre

La solution suivante semble être beaucoup plus propre pour moi et elle est aussi suggérée par le Git lui-même - essayez d'exécuter git status dans le référentiel avec un conflit:

Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

Faisons donc ce que suggère Git (sans faire de commits inutiles):

  1. Manuellement (ou à l'aide d'un outil de fusion , voir ci-dessous), résolvez le (s) conflit (s).
  2. Utilisez git reset pour marquer les conflits comme résolus et annulez les modifications. Vous pouvez l'exécuter sans aucun paramètre et Git supprimera tout de l'index. Vous n'êtes pas obligé d'exécuter git add avant.
  3. Enfin, supprimez le stash avec git stash drop, car Git ne le fait pas en cas de conflit.

Traduit en ligne de commande:

$ git stash pop

# ...resolve conflict(s)

$ git reset

$ git stash drop

Explication du comportement par défaut

Il existe deux manières de marquer les conflits comme résolus: git add et git reset. Alors que git reset marque les conflits comme étant résolus et supprime les fichiers de l'index, git add marque également les conflits comme étant résolus, mais conserve les fichiers dans l'index.

L'ajout de fichiers à l'index après la résolution d'un conflit est volontaire. De cette façon, vous pouvez différencier les modifications de la réserve précédente et des modifications apportées une fois le conflit résolu. Si vous ne l'aimez pas, vous pouvez toujours utiliser git reset pour tout supprimer de l'index.

Fusionner les outils

Je recommande fortement d'utiliser l'un des outils de fusion à 3 voies pour résoudre les conflits, par ex. KDiff , Meld , etc., au lieu de le faire manuellement. Il résout généralement tous les conflits ou la majorité des conflits automatiquement. C'est énorme gain de temps!

387

Supposons que vous ayez ce scénario dans lequel vous stockez vos modifications pour pouvoir extraire Origin. Peut-être parce que vos modifications locales ne sont que debug: true dans certains fichiers de paramètres. Maintenant, vous tirez et quelqu'un y a introduit un nouveau paramètre, 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")

D'accord. J'ai décidé d'aller avec ce que Git avait suggéré: j'ai résolu le conflit et 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 souhaite 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 ça!

git reset HEAD^

Ma copie de travail n'a pas été modifiée, mais le commit WIP est parti. C'est exactement ce que je voulais! (Notez que je n'utilise pas --soft ici, car s'il y a des fichiers fusionnés automatiquement dans votre réserve, ils sont automatiquement mis en scène et vous vous retrouveriez avec ces fichiers à nouveau mis en place 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 avec des conflits; dans ce cas, elle n'est pas supprimée de la liste de cache. Vous devez résoudre le conflits à la main et appelez git stash drop manuellement ensuite. " C'est donc exactement ce que nous faisons maintenant:

git stash drop

Et fait.

292
scy

Au lieu d'ajouter les modifications que vous avez apportées pour résoudre le conflit, vous pouvez utiliser git reset HEAD file pour résoudre le conflit sans organiser vos modifications.

Cependant, vous devrez peut-être exécuter cette commande deux fois. Une fois pour marquer le conflit comme résolu et une fois pour décomposer les changements mis en scène par la routine de résolution de conflit.

Il est possible qu’il existe un mode de réinitialisation qui effectue ces deux opérations simultanément, bien qu’il n’y en ait pas maintenant.

84
ComputerDruid
git checkout stash -- .

a travaillé pour moi.

Note: Cela peut être dangereux car il n'essaie pas de fusionner les modifications de la réserve dans votre copie de travail, mais écrase avec les fichiers stockés à la place. Ainsi, vous pouvez perdre vos modifications non validées.

23
mr.musicman
git add .
git reset

git add . organisera TOUS les fichiers indiquant à git que vous avez résolu le conflit.

git reset désarchivera TOUS les fichiers mis en scène sans créer de commit.

6
Aaron Goldman

Il semble que ce soit peut-être la solution que vous recherchez. Je n'ai pas encore essayé personnellement, mais il semble que cela puisse faire l'affaire. Avec cette commande, GIT essaiera d'appliquer les modifications comme elles étaient auparavant, sans essayer de toutes les ajouter pour la validation.

git stash apply --index

voici l'explication complète:

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

4
Marco Ponti

git stash branch fonctionnera, ce qui créera une nouvelle branche pour vous, vérifiera le commit que vous étiez sur lorsque vous avez caché votre travail, y réapplique votre travail, puis supprime la cachette si elle est appliquée avec succès. vérifier this

2
cherish

Le moyen le plus rapide que j'ai trouvé est de résoudre le conflit, puis faites git add -u, puis faites git reset HEAD, cela n'implique même pas une validation.

2
Jammer

Selon git stash questions , après avoir résolu le conflit, git add <file> est la bonne solution.

C'est après avoir lu ce commentaire que j'ai compris que les modifications sont automatiquement ajoutées à l'index (par conception). C'est pourquoi git add <file> achève le processus de résolution des conflits.

1
samgrigg