206 votes

Git merge avec la force d'écraser

J'ai une branche appelée demo qui j'ai besoin de fusionner avec d' master de la branche. Je peux obtenir le résultat souhaité avec les commandes suivantes:

git pull origin demo
git checkout master
git pull origin master
git merge demo
git push origin master

Ma seule préoccupation est que si il y a tout de fusion questions, je veux dire git d'écraser les modifications en master de la branche, sans me donner de fusion invite. Donc en gros changements en demo de la branche devrait automatiquement écraser les modifications en master de la branche.

Je regardai autour de moi il y a plusieurs options, mais je ne veux pas prendre de risque avec la fusion.

188voto

torek Points 25463

Pas vraiment liée à cette réponse, mais je préfère le fossé git pull, qui dirige git fetch suivie par git merge. Vous faites trois fusionne, qui va faire de votre Git exécuter trois opérations d'extraction, lorsque l'un fetch est tout ce dont vous aurez besoin. Donc:

git fetch origin   # update all our origin/* remote-tracking branches

git checkout demo         # if needed -- your example assumes you're on it
git merge origin/demo     # if needed -- see below

git checkout master
git merge origin/master

git merge -X theirs demo   # but see below

git push origin master     # again, see below

Le contrôle de la plus délicate de la fusion

La partie la plus intéressante ici est - git merge -X theirs. Comme root545 noté, l' -X des options sont passés à la fusion de la stratégie, et à la fois la valeur par défaut recursive de la stratégie et de l'alternative resolve stratégie prenne -X ours ou -X theirs (l'un ou l'autre, mais pas les deux). Pour comprendre ce qu'ils font, cependant, vous devez savoir comment Git trouve, et des friandises, des conflits de fusion.

Un conflit de fusion peut se produire dans certains fichier1 lorsque la base de la version différente de celle du courant (également appelée locales, de la TÊTE, ou --ours) de la version et les autres (aussi appelé remote ou --theirs) version de ce même fichier. Qui est, la fusion a identifié trois révisions (trois commits): de base, la nôtre et la leur. La "base" est à partir de la fusion de la base entre notre engagement et de leur livraison, que l'on trouve dans le commit graphique (pour beaucoup plus sur ce sujet, voir les autres StackOverflow messages). Git a ensuite trouvé deux séries de changements: "ce que nous avons fait" et "ce qu'ils ont fait". Ces changements sont (en général) qui se trouve sur une ligne-par-ligne, purement textuelle de base. Git a pas de réelle compréhension du contenu du fichier; il s'agit simplement d'une comparaison de chaque ligne de texte.

Ces changements sont ce que vous voyez en git diff de sortie, et comme toujours, ils ont contexte ainsi. Il est possible que les choses on changé, ce sont sur des lignes différentes à partir des choses qu'ils ont changé, de sorte que les changements semblent comme ils ne serait pas entrer en collision, mais le contexte a également changé (p. ex., en raison de notre changement de fermer vers le haut ou le bas du fichier, de sorte que le fichier s'exécute dans notre version, mais dans le leur, ils ont également ajouté plus de texte en haut ou en bas).

Si les modifications se produisent sur différentes lignes-par exemple, nous changeons color de colour sur la ligne 17 et ils changent fred de barney sur la ligne 71-alors il n'y a pas de conflit: Git prend simplement les deux changements. Si les changements se font sur les mêmes lignes, mais sont identiques changements, Git prend une copie de la modification. Seulement si les modifications sont sur les mêmes lignes, mais sont différents changements, ou le cas d'interférer contexte, pensez-vous obtenir un modifier/modifier le conflit.

L' -X ours et -X theirs options indiquer à Git comment faire pour résoudre ce conflit, en sélectionnant simplement l'un des deux changements: la nôtre ou la leur. Puisque vous avez dit que vous fusionnez demo (pour eux) en master (la nôtre) et souhaitez que les modifications de demo, vous souhaitez -X theirs.

Aveuglément appliquant -X, cependant, est dangereux. Tout simplement parce que nos changements ne sont pas en conflit, ligne par ligne, ne signifie pas que nos modifications n'entrent pas en conflit! Un exemple classique se produit dans les langues avec les déclarations de variables. La version de base peut déclarer une variable inutilisée:

int i;

Dans notre version, nous avons supprimer la variable inutilisée de faire un avertissement du compilateur d'aller plus loin-et dans leur version, ils ajoutent une boucle quelques lignes plus loin, à l'aide de i que le compteur de la boucle. Si l'on combine les deux modifications, le code ne compile plus. L' -X option n'est d'aucune aide ici, car les changements sont sur des lignes différentes.

Si vous avez un test automatisé suite, la chose la plus importante à faire est d'exécuter les tests après la fusion. Vous pouvez le faire après avoir commis, et de fixer des choses plus tard, si nécessaire; ou vous pouvez le faire avant de commettre, par l'ajout d' --no-commit de la git merge commande. Nous allons laisser les détails de tout cela à d'autres offres.


1Vous pouvez également obtenir des conflits avec "fichier" -" à l'échelle des opérations, par exemple, nous avons peut-être corriger l'orthographe d'un mot dans un fichier (de sorte que nous avons un changement), et ils ont supprimer le fichier en entier (de sorte qu'ils ont une suppression). Git ne permettra pas de résoudre ces conflits sur son propre, indépendamment de l' -X arguments.


Faire moins de fusions et/ou le plus intelligent des fusions et/ou de l'utilisation de rebase

Il y a trois fusionne dans nos deux séquences de commande. Le premier est d'amener origin/demo local demo (la vôtre utilise git pull qui, si votre Git est très ancienne, ne va pas de mise à jour de origin/demo mais produira le même résultat final). La deuxième est d'amener origin/master en master.

Il n'est pas clair pour moi, qui est la mise à jour de demo et/ou master. Si vous écrivez votre propre code sur votre propre demo de la branche, et d'autres sont de l'écriture de code et en le poussant à l' demo branche sur origin, puis de cette première étape de fusion peut avoir de conflits, ou de produire une véritable fusion. Plus souvent que pas, il est préférable d'utiliser git rebase, plutôt que de les fusionner, de les combiner travail (certes, c'est une question de goût et d'opinion). Si oui, vous pouvez utiliser git rebase à la place. D'autre part, si vous ne font pas du tout de votre propre s'engage sur demo, vous n'avez même pas besoin d' un demo de la branche. Alternativement, si vous souhaitez automatiser beaucoup de cela, mais être en mesure de vérifier soigneusement quand il y a engage que vous et d'autres, ont pris, vous pourriez vouloir utiliser git merge --ff-only origin/demo: cela permettra d'avancer rapidement dans votre demo pour correspondre à la mise à jour de origin/demo si possible, et il suffit d'emblée à l'échec si pas (à ce point, vous pouvez inspecter les deux ensembles de modifications, et de choisir une vraie fusion ou un rebase selon le cas).

Cette même logique s'applique à l' master, même si vous faites de la fusion sur master, alors vous avez certainement besoin d'un master. Il est, cependant, même de chances que vous voulez de la fusion à l'échec si elle ne peut pas être fait, comme une avance rapide de la non-fusion, donc c'est probablement ce qui devrait également être git merge --ff-only origin/master.

Disons que vous ne jamais faire votre propre s'engage sur demo. Dans ce cas, on peut changer le nom de l' demo entièrement:

git fetch origin   # update origin/*

git checkout master
git merge --ff-only origin/master || die "cannot fast-forward our master"

git merge -X theirs origin/demo || die "complex merge conflict"

git push origin master

Si vous êtes de faire votre propre demo de la branche s'engage, ce n'est pas utile; vous pouvez ainsi garder la fusion existant (mais peut-être ajouter --ff-only selon le genre de comportement que vous voulez), ou de passer pour faire un rebase. À noter que les trois méthodes peuvent échouer: la fusion peut échouer avec un conflit de fusion avec d' --ff-only peut ne pas être en mesure d'avancer rapidement, et cela peut échouer avec un conflit (rebase œuvres, en substance, l'écrémage s'engage, qui utilise la fusion des machines et, par conséquent, peut obtenir un conflit de fusion).

17voto

manuj Points 1931

Vous pouvez essayer de "nous" option dans git merge,

git merge de la branche X nôtre

Cette option forces contradictoires beau pour être auto-résolu proprement en favorisant notre version. Les modifications de l'autre arbre qui n'entrent pas en conflit avec notre côté sont reflétées dans le résultat de la fusion. Pour un fichier binaire, le contenu entier sont prises à partir de notre côté.

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