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).