web-dev-qa-db-fra.com

Git pull génère des messages "Fusionner la branche" superflus dans le journal de validation

Je travaille avec un autre développeur sur un projet et nous utilisons Github comme référentiel à distance. Je suis sur un Mac avec Git 1.7.7.3, il est sous Windows avec Git 1.7.6.

C'est ce qui se passe

  1. L'un de nous (appelons-le développeur A, mais peu importe lequel) envoie un ensemble de commits à GitHub.
  2. L'autre (développeur B) effectue des commits locaux.
  3. B fait un git pull.
  4. B fait un git Push.
  5. En regardant l'historique de validation, je vois fusionner le "maître" de la branche de github.com:foo/bar

Le journal de validation est parsemé de messages "Fusionner la branche" au fil du temps et indique également au développeur B que les modifications qu'il a apportées sont validées. Le seul moyen que nous avons trouvé pour éviter ce problème consiste à effectuer un git pull --rebase à l’étape 3, mais je ne sais pas quels seront les effets secondaires du rebasement. C’est la première fois que je travaille sur un repo git multi-développeurs, est-ce donc un comportement normal? Des idées sur la façon de résoudre ce problème?

97
mshafrir

Le commit que vous voyez est parfaitement correct. Un pull exécute effectivement git fetch et alors git merge donc une fusion se produit généralement lorsque vous exécutez git pull.

L'alternative consistant à utiliser un rebasement au lieu d'une fusion est possible, mais vous devez généralement l'éviter. Le changement de base vous permet de conserver un historique linéaire, mais supprime également toutes les informations relatives à la création de branche. Cela entraînera également la réécriture de l'historique de la branche actuelle, recréant tous les commits ne figurant pas dans la branche cible (dans votre cas, la commande à distance). Comme les commits recréés sont différents, cela peut causer beaucoup de confusion lors du développement avec d'autres, en particulier lorsque des personnes ont déjà extrait certaines parties de ces commissions avant qu'elles ne soient réécrites (par exemple avec des branches de fonctionnalités). Donc, en règle générale, vous devriez jamais réécrire tout commit déjà poussé.

Les commits que vous voyez sont là pour combiner deux (ou plus) branches. Il est parfaitement correct d'avoir un commit qui ne fait que fusionner plusieurs branches. En fait, il est très clair que vous avez un commit de fusion qui combine les branches lorsque vous consultez l'historique. Par rapport au changement de base, la fusion vous permet également de voir efficacement l'historique original tel qu'il a été développé, y compris les branches réelles qui ont coexisté.

Donc, histoire longue: Oui, avoir des commits de fusion est parfaitement correct et vous ne devriez pas vous inquiéter pour eux.

85
poke

Cette réponse a été révisée car ma compréhension, les diagrammes et les conclusions étaient incorrects.


git pull provoque la fusion des fusions, car git est en train de fusionner. Cela peut être changé en configurant vos branches pour qu'elles utilisent rebase au lieu de fusionner. L'utilisation de rebase au lieu d'une fusion sur une extraction fournit un historique plus linéaire au référentiel partagé. Par contre, les commits de fusion montrent les efforts de développement parallèles sur la branche.

Par exemple, deux personnes travaillent sur la même branche. La branche commence comme:

...->C1

La première personne termine son travail et pousse vers la branche:

...->C1->C2

La deuxième personne termine son travail et veut pousser, mais ne peut pas, car ils ont besoin de mettre à jour. Le référentiel local de la deuxième personne ressemble à ceci:

...->C1->C3

Si l'extraction est configurée pour fusionner, le référentiel de la deuxième personne ressemblera.

...->C1->C3->M1
      \      /
       ->C2->

Où M1 est un commit de fusion. Cette nouvelle histoire de branche sera poussée au repo. Si au lieu de cela, le pull est configuré pour rebaser le repo local ressemblerait à ceci:

...->C1->C2->C3

Il n'y a pas de commit de fusion. L'histoire a été rendue plus linéaire.

Les deux choix reflètent l'histoire de la branche. git vous permet de choisir quelle histoire vous préférez.

Il existe en effet des endroits où rebase peut causer un problème avec les branches distantes. Ce n'est pas un de ces cas. Nous préférons utiliser rebase car cela simplifie un historique de branche déjà compliqué et affiche une version de l'historique par rapport au référentiel partagé.

Vous pouvez définir branch.autosetuprebase = toujours pour que git établisse automatiquement vos branches distantes en tant que rebase au lieu de master.

git config --global branch.autosetuprebase always

Ce paramètre force git à créer automatiquement un paramètre de configuration pour chaque branche distante:

branch.<branchname>.rebase=true

Vous pouvez définir cela vous-même pour vos branches distantes déjà configurées.

git config branch.<branchname>.rebase true

Je voudrais remercier @LaurensHolst d’avoir interrogé et poursuivi mes déclarations précédentes. J'ai certainement appris davantage sur la façon dont git fonctionne avec les commits pull et fusion.

Pour plus d'informations sur les validations de fusion, vous pouvez lire Contribution à un projet dans ProGit-Book . La section Private Small Team indique les commits de fusion.

46
Bill Door

Tu peux faire:

git pull --rebase

Toutefois, vos modifications resteront toujours au-dessus de celles de vos collaborateurs. Mais vous ne recevrez aucun message de fusion polluant.

9
gaborous

Faire un git pull va insérer les messages "Fusionner la branche", c'est ce que ça fait. En faisant un pull, vous avez fusionné la branche distante dans votre branche locale.

Lorsque vous effectuez une extraction git et qu'il existe des conflits, le journal git affiche les mises à jour des fichiers en conflit comme provenant de l'utilisateur qui a résolu les conflits. J'imagine que c'est parce que la personne qui résout le conflit réengage le fichier.

Autant que je sache, c'est comme ça que ça fonctionne, et il n'y a pas de solution.

Le rebasonnement effacera l’historique des git, vous ne pourrez donc pas voir quand les fusions ont eu lieu.

7
kclair

Il existe en fait une réponse beaucoup plus simple à cette question. Il suffit que le développeur B fasse un pull AVANT de s’engager. Cela empêchera ces validations de fusion, car elles sont causées par l'historique que vous avez créé sur votre référentiel local à partir de votre validation locale et essayant de fusionner avec l'historique des validations du référentiel distant. Si vous recevez un message indiquant que quelque chose du genre "les modifications seront écrasées" lors d'un pull, cela signifie simplement que vous avez touché le même fichier, faites-le:

git stash
git pull
git stash pop

alors vous pouvez résoudre tous les conflits de fusion s'il y en a.

6
Luke