Comment ignorer les modifications à distance et marquer un fichier comme «résolu»?

197

J'ai des fichiers locaux, je tire de la branche distante et il y a des conflits. Je sais que je souhaite conserver mes modifications locales et ignorer les modifications à distance provoquant des conflits. Existe-t-il une commande que je peux utiliser pour dire "marquer tous les conflits comme résolus, utiliser local"?

Tom DeMille
la source
1
La réponse ci-dessous a été super éclairante pour moi. Il y a quelques points subtils qui clarifient vraiment les choses pour moi, je recommande à tous les utilisateurs de GIT non experts de lire tous les commentaires ci-dessous, et merci Brian!
Tom DeMille

Réponses:

332

git checkouta la --ourspossibilité d'extraire la version du fichier que vous aviez localement (par opposition à --theirs, qui est la version que vous avez extraite). Vous pouvez passer .à git checkoutpour lui dire de tout vérifier dans l'arbre. Ensuite, vous devez marquer les conflits comme résolus, ce que vous pouvez faire git addet valider votre travail une fois terminé:

git checkout --ours .  # checkout our local version of all files
git add -u             # mark all conflicted files as merged
git commit             # commit the merge

Notez le .dans la git checkoutcommande. C'est très important et facile à manquer. git checkouta deux modes; celui dans lequel il change de branche et celui dans lequel il extrait les fichiers de l'index dans la copie de travail (en les tirant parfois dans l'index d'une autre révision en premier). La façon dont il se distingue est de savoir si vous avez passé un nom de fichier; si vous n'avez pas passé de nom de fichier, il essaie de changer de branche (mais si vous ne passez pas non plus de branche, il essaiera simplement de vérifier à nouveau la branche actuelle), mais il refuse de le faire s'il y a des fichiers modifiés que cela se produirait. Donc, si vous voulez un comportement qui écrasera les fichiers existants, vous devez passer .ou un nom de fichier afin d'obtenir le deuxième comportement git checkout.

C'est aussi une bonne habitude d'avoir, en passant un nom de fichier, pour le compenser avec --, comme git checkout --ours -- <filename>. Si vous ne le faites pas et que le nom de fichier correspond au nom d'une branche ou d'une balise, Git pensera que vous voulez vérifier cette révision, au lieu de vérifier ce nom de fichier, et utilisez donc la première forme de la checkoutcommande .

Je vais développer un peu sur la façon dont les conflits et la fusion fonctionnent dans Git. Lorsque vous fusionnez dans le code de quelqu'un d'autre (ce qui se produit également lors d'un pull; un pull est essentiellement un fetch suivi d'une fusion), il y a peu de situations possibles.

Le plus simple est que vous êtes sur la même révision. Dans ce cas, vous êtes "déjà à jour" et rien ne se passe.

Une autre possibilité est que leur révision soit simplement une descendante de la vôtre, auquel cas vous aurez par défaut une "fusion rapide", dans laquelle votre HEADest juste mis à jour à leur commit, sans fusion se produisant (cela peut être désactivé si vous vraiment envie d'enregistrer une fusion, en utilisant --no-ff).

Ensuite, vous entrez dans les situations dans lesquelles vous devez réellement fusionner deux révisions. Dans ce cas, deux résultats sont possibles. La première est que la fusion se déroule proprement; toutes les modifications se trouvent dans des fichiers différents, ou sont dans les mêmes fichiers mais suffisamment éloignés pour que les deux ensembles de modifications puissent être appliqués sans problème. Par défaut, lorsqu'une fusion propre se produit, elle est automatiquement validée, mais vous pouvez la désactiver --no-commitsi vous devez la modifier au préalable (par exemple, si vous renommez la fonction fooen bar, et que quelqu'un d'autre ajoute un nouveau code qui appelle foo, il fusionnera proprement , mais produisez un arbre cassé, donc vous voudrez peut-être le nettoyer dans le cadre de la validation de fusion afin d'éviter d'avoir des validations cassées).

La dernière possibilité est qu'il y ait une véritable fusion et qu'il y ait des conflits. Dans ce cas, Git fera autant de la fusion comme il peut, et les fichiers de produire avec des marqueurs de conflit ( <<<<<<<, =======et >>>>>>>) dans votre copie de travail. Dans l'index (également connu sous le nom de "zone de transit"; l'endroit où les fichiers sont stockés git addavant de les valider), vous aurez 3 versions de chaque fichier avec des conflits; il existe la version d'origine du fichier de l'ancêtre des deux branches que vous fusionnez, la version de HEAD(votre côté de la fusion) et la version de la branche distante.

Afin de résoudre le conflit, vous pouvez soit modifier le fichier qui se trouve dans votre copie de travail, supprimer les marqueurs de conflit et corriger le code afin qu'il fonctionne. Vous pouvez également extraire la version de l'un ou l'autre côté de la fusion à l'aide de git checkout --oursou git checkout --theirs. Une fois que vous avez placé le fichier dans l'état souhaité, vous indiquez que vous avez terminé de fusionner le fichier et qu'il est prêt à être validé à l'aide de git add, puis vous pouvez valider la fusion avec git commit.

Brian Campbell
la source
7
Vous devriez probablement noter que git add --alltous les fichiers sont ajoutés au référentiel, ce qui peut ajouter plus de fichiers que prévu, sauf si vos .gitignoremodèles sont en parfait état. git add -uest probablement plus adapté à cette situation, vous êtes moins susceptible d'avoir des modifications aux fichiers suivis que vous ne souhaitez pas ajouter lors de la résolution d'une fusion.
CB Bailey
Oops désolé. C'est ce que je voulais dire. Corrigé maintenant.
Brian Campbell
1
merci pour votre réponse détaillée. J'ai en fait essayé git checkout --ours et reçu un message d'erreur (dont je ne me souviens pas maintenant). Les fichiers en question sont des DLL (nous en avons quelques-uns que nous faisons cachés, des références tierces pour la plupart) et je voulais juste dire `` ok, ma copie est celle que je veux, mais l'erreur était quelque chose comme '' impossible de vérifier lors de la fusion '' ..... Je garderai cet article comme référence et la prochaine fois que cela se produira, réessayez et voyez si cela fonctionne ou si je peux poster ce message. Merci encore
Tom DeMille
mais votre explication m'éclaircit beaucoup sur le processus, merci encore ... Question de suivi: Est-il possible d'obtenir git pour supprimer les fichiers .orig une fois la fusion effacée?
Tom DeMille
2
Tu dois faire git checkout --ours .. Le .est important; la transmission d'un nom de fichier (dans ce cas, l'ensemble du répertoire) sélectionne entre deux modes de fonctionnement différents checkout, l'un qui change de branche et l'autre qui déplace les fichiers de l'index vers la copie de travail. Je suis d'accord, c'est très déroutant. Vous pouvez également faire git checkout --ours -- <filename>pour vérifier un fichier individuel à la fois.
Brian Campbell
23

Assurez-vous de l'origine du conflit: s'il est le résultat d'un git merge, voir la réponse de Brian Campbell .

Mais si est le résultat d'un git rebase, afin d'éliminer (leurs) modifications à distance et d'utiliser des modifications locales , vous devrez faire:

git checkout --theirs -- .

Voir " Pourquoi la signification de" ours"et" theirs"est-elle inversée" "pour voir comment ourset theirssont échangés lors d'un rebase (car la branche en amont est extraite ).

VonC
la source