Pourquoi est-ce que je fusionne «l'origine / développement» de la branche de suivi à distance en développement »?

125

Je suis le seul de mon organisation à effectuer des validations avec le message suivant:

Fusionner la branche de suivi à distance `` origine / développement '' en développement

Je ne sais pas ce que je fais pour les provoquer, mais j'aimerais arrêter.

Quelle commande suis-je en train d'émettre pour créer ce commit et quelle commande dois-je utiliser pour ne pas le produire?

Jordan Feldstein
la source
1
La réponse de Richard Hansen est bonne. Mais je pense que cela pourrait être déroutant pour les débutants. Ma solution est de continuer à faire pull --rebase mais pour éviter le danger, je range mes modifications avant le pull. Puis, après avoir tiré, je l'applique. Je résous les conflits. Enfin je peux m'engager et pousser.
Johnjohn
git pull --autostash --rebaseFonctionne- t-il pour vous @Johnjohn?
sourcedelica

Réponses:

206

git pullcrée probablement le commit. Si vous effectuez un commit local et que vous l'exécutez git pullaprès que quelqu'un d'autre a poussé un commit vers le référentiel, Git télécharge le commit de l'autre développeur, puis le fusionne dans votre branche locale.

Comment éviter ces commits de fusion à l'avenir

Vous pouvez l'utiliser git pull --rebasepour éviter que cela ne se produise à l'avenir, mais le rebasage a ses risques et je recommande d'éviter pullcomplètement .

Au lieu de cela, je vous encourage à suivre ce modèle d'utilisation:

# download the latest commits
git remote update -p

# update the local branch
git merge --ff-only @{u}

# if the above fails with a complaint that the local branch has
# diverged:
git rebase -p @{u}

Explication

  • git remote update -ptélécharge tous les commits dans les référentiels distants et met à jour les branches de suivi distantes (par exemple, origin/master). Il ne touche PAS votre répertoire de travail, votre index ou vos branches locales.

    L' -pargument élague les branches en amont supprimées. Ainsi, si la foobranche est supprimée dans le originréférentiel, git remote update -psupprimera automatiquement votre origin/fooref.

  • git merge --ff-only @{u}dit à Git de fusionner la branche amont (l' @{u}argument) dans votre branche locale, mais seulement si votre branche locale peut être "acheminée rapidement" vers la branche amont (en d'autres termes, si elle n'a pas divergé).

  • git rebase -p @{u}déplace efficacement les commits que vous avez faits mais que vous n'avez pas encore poussés au-dessus de la branche amont, ce qui élimine le besoin de créer les commits de fusion stupides que vous essayez d'éviter. Cela améliore la linéarité de l'historique de développement, ce qui facilite son examen.

    L' -poption indique à Git de conserver les fusions. Cela empêche Git de linéariser les commits en cours de rebasage. Ceci est important si, par exemple, vous avez fusionné une branche de fonctionnalité dans master. Sans -p, chaque commit sur la branche de fonctionnalité serait dupliqué dans masterle cadre de la linéarisation effectuée par git rebase. Cela rendrait l'historique du développement plus difficile à examiner, pas plus facile.

    Attention : il se git rebasepeut que vous ne fassiez pas ce que vous attendez de lui, alors examinez les résultats avant de pousser. Par exemple:

    git log --graph --oneline --decorate --date-order --color --boundary @{u}..
    

Je préfère cette approche git pull --rebaseaux raisons suivantes:

  • Il vous permet de voir les commits amont entrants avant de modifier votre historique pour les incorporer.
  • Il vous permet de passer l' option -p( --preserve-merges) à git rebaseau cas où vous auriez besoin de rebaser une fusion intentionnelle (par exemple, la fusion d'une branche de fonctionnalité déjà poussée dans master).

Sténographie: git upau lieu degit pull

Pour faciliter les opérations ci-dessus, je recommande de créer un alias appelé up:

git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'

Maintenant, tout ce que vous avez à faire pour mettre à jour votre branche est d'exécuter:

git up

au lieu de git pull. Si vous obtenez une erreur parce que votre branche locale a divergé de la branche amont, c'est votre signal de rebase.

Pourquoi pas git pull --rebase?

Courir git pull --rebaseéquivaut à courir git fetchsuivi de git rebase. Cela tente d'avancer rapidement vers les nouveaux commits en amont, mais si ce n'est pas possible, il rebase vos commits locaux sur les nouveaux commits en amont. C'est généralement OK, mais soyez prudent:

  • Rebase est un sujet avancé, et vous devez comprendre les implications avant de rebaser.
  • git pull --rebasene vous donne pas la possibilité d'examiner les commits avant de les incorporer. En fonction de l' amont changé, il est tout à fait possible que rebasage est le mauvais fonctionnement d' un rebase --onto, merge, resetou push -fpeut - être plus approprié que d' une plaine rebase.
  • Il n'est pas (actuellement) possible de passer --preserve-mergesà l'opération de rebase, donc toute fusion intentionnelle d'une branche de fonctionnalité sera linéarisée, rejouant (et donc dupliquant) tous les commits de branche de fonctionnalité.

"Correction" d'un commit de fusion existant créé par git pull

Si vous n'avez pas encore poussé un commit de fusion créé par git pull, vous pouvez rebaser le commit de fusion. En supposant que vous n'ayez effectué aucune fusion intentionnelle (par exemple, la fusion d'une branche de fonctionnalité déjà poussée dans votre branche actuelle), ce qui suit devrait le faire:

git rebase @{u}

La commande ci-dessus indique à Git de sélectionner tous les commits non-merge accessibles depuis HEAD(le commit actuel), moins tous les commits accessibles depuis @{u}(ce qui est un raccourci pour "la branche amont", c'est-à-dire, origin/mastersi HEADc'est le cas master), replay (cherry-pick ) les au-dessus de la branche amont, puis déplacez la référence de branche actuelle pour qu'elle pointe vers le résultat de la relecture des validations. Cela déplace effectivement les commits non-merge vers le commit amont le plus récent, ce qui élimine la fusion créée par git pull.

Si vous avez un commit de fusion intentionnel, vous ne voulez pas l'exécuter git rebase @{u}car il rejouera tout depuis l'autre branche. Traiter ce cas est beaucoup plus compliqué, c'est pourquoi il est bon d'utiliser git upet d'éviter git pulltout à fait. Vous devrez probablement utiliser resetpour annuler la fusion créée par pull, puis le faire git rebase -p @{u}. L' -pargument de git rebasen'a pas fonctionné de manière fiable pour moi, vous pourriez donc devoir utiliser resetpour annuler la fusion intentionnelle, mettre à jour votre branche locale vers @{u}, puis refaire la fusion intentionnelle (ce qui est pénible s'il y avait beaucoup de fusion poilue conflits).

Richard Hansen
la source
+1 pour discuter de --preserve-merges, sauf que vous n'avez pas réellement documenté cela dans les commandes que vous lui avez dit d'exécuter, donc -1 pour cela.
Seth Robertson
@Seth: Merci pour le commentaire; J'ai mis à jour la réponse pour recommander -p. J'ai évité de le recommander auparavant car il n'est pas nécessaire très souvent et son comportement n'est pas bien documenté.
Richard Hansen
3
Quelle est la différence entre git remote update -pet git fetch?
eckes le
3
@eckes: git remote update -pest le même que git fetch --all -p. J'ai pris l'habitude de l'utiliser git remote update -pquand je fetchn'avais pas l' -poption.
Richard Hansen
1
@ user1914692: Une fois la fusion terminée, Git mettra à jour la branche locale pour qu'elle pointe vers le commit de fusion nouvellement créé, pas vers le même commit que la branche distante. Ce nouveau commit de fusion est le problème, surtout lorsqu'il est poussé.
Richard Hansen
18
git fetch
git rebase origin/master

Ça devrait le faire. Ou si vous souhaitez continuer à utiliser pull

git pull --rebase

Vous pouvez également configurer cette branche dans votre configuration pour qu'elle rebase automatiquement, ou être configurée comme cela automatiquement pour toute autre branche de suivi future que vous créez. Ensuite, vous pouvez revenir à la simple utilisation

git pull

Plus d'informations à ce sujet dans la section "Pull with rebase au lieu de fusionner" de cette page:

http://mislav.uniqpath.com/2010/07/git-tips/

Adam Dymitruk
la source