2385 votes

Quelle est la meilleure (et la plus sûre) façon de fusionner une branche Git dans master ?

Une nouvelle branche de master est créé, nous l'appelons test .

Il y a plusieurs développeurs qui s'engagent soit à master ou créer d'autres branches et les fusionner plus tard dans master .

Disons que le travail sur test prend plusieurs jours et vous voulez continuer à garder test mis à jour avec des commits dans master .

Je ferais git pull origin master de test .

Question 1 : Est-ce la bonne approche ? D'autres développeurs auraient pu facilement travailler sur les mêmes fichiers que moi.


Mon travail sur test est terminé et je suis prêt à le fusionner de nouveau avec master . Voici les deux moyens auxquels je pense :

A :

git checkout test
git pull origin master
git push origin test
git checkout master
git pull origin test 

B :

git checkout test
git pull origin master
git checkout master
git merge test

Je n'utilise pas --rebase parce que d'après ce que j'ai compris, rebase récupérera les modifications de master et empiler le mien par-dessus, ce qui pourrait écraser les changements faits par d'autres personnes.

Question 2 : Laquelle de ces deux méthodes est la bonne ? Quelle est la différence ?

Le but dans tout ça est de garder mon test mis à jour avec les choses qui se passent dans master et plus tard, je pourrais les fusionner à nouveau dans master en espérant garder la chronologie aussi linéaire que possible.

27 votes

Non rebase n'écrase jamais, il essaie juste d'obtenir un historique plus propre. en rattachant (ou en falsifiant) l'historique au dernier point du maître

9 votes

Rebase n'écrase pas vos commits. Il annule vos commits, applique les commits de la branche master à votre branche test, puis applique vos commits à nouveau à test.

1 votes

Que faire si nous n'avons pas d'accès en écriture à master ? Y a-t-il un moyen de résoudre les conflits de manière préemptive sur la branche des fonctionnalités ? Probablement pas, je suppose, puisque les histoires ont probablement divergé.

3357voto

KingCrunch Points 45168

Comment je m'y prendrais

git checkout master
git pull origin master
git merge test
git push origin master

Si j'ai une branche locale à partir d'une branche distante, je ne me sens pas à l'aise pour fusionner d'autres branches que celle-ci avec la branche distante. De plus, je ne pousserais pas mes changements tant que je ne suis pas satisfait de ce que je veux pousser et je ne pousserais pas du tout les choses qui ne concernent que moi et mon dépôt local. Dans votre description, il semble que test est seulement pour vous ? Donc aucune raison de le publier.

git essaye toujours de respecter vos changements et ceux des autres, et il en sera ainsi --rebase . Je ne pense pas pouvoir l'expliquer de manière appropriée, alors jetez un coup d'œil sur le site suivant le livre de Git - Rebasage o git-ready : Introduction au rebasing pour une petite description. C'est une fonction assez cool

3 votes

git merge test me donne fatal: 'test' does not point to a commit . Je dois regarder dans git log pour le point de livraison sur la branche de test, revenir à la branche principale, puis faire git merge 0f37d3154abbf52a4cbbbb5109f08af6a7567234 .

18 votes

@Duncanmoo Eh bien, bien sûr la branche test doit exister. Bien sûr, vous pouvez utiliser le hash du commit à la place, mais il est généralement plus facile d'utiliser le nom de la branche. En interne, il récupère simplement le hash de HEAD de la branche.

48 votes

@shanyangqu Pour obtenir les derniers changements à partir de la télécommande. Si vous travaillez seul et avec un seul système, il n'y a pas de problème. Mais lorsqu'il y a des changements poussés à partir d'un système différent (probablement d'un développeur différent), vous verrez un conflit dès que vous essayez de pousser votre fusion en arrière (la 4ème étape). La seule solution est alors de fusionner votre master local dans le master distant, ce qui aboutit à un commit de fusion "merged master into origin/master" assez laid. C'est donc toujours une bonne idée de faire un pull avant la fusion.

471voto

John Yin Points 325

Il s'agit d'une question très pratique, mais toutes les réponses ci-dessus ne sont pas pratiques.

Comme

git checkout master
git pull origin master
git merge test
git push origin master

Cette approche a deux questions :

  1. Ce n'est pas sûr, car nous ne savons pas s'il y a des conflits entre la branche de test et la branche principale.

  2. Cela "comprimerait" tous les commits de test en un seul commit de fusion sur master ; c'est-à-dire que sur la branche master, nous ne pouvons pas voir tous les journaux de changement de la branche test.

Ainsi, lorsque nous soupçonnons qu'il y a des conflits, nous pouvons effectuer les opérations git suivantes :

git checkout test
git pull 
git checkout master
git pull
git merge --no-ff --no-commit test

Test merge avant commit pour éviter une validation rapide par --no-ff ,

Si un conflit est rencontré, nous pouvons lancer git status pour vérifier les détails des conflits et essayer de les résoudre.

git status

Une fois que nous avons résolu les conflits, ou s'il n'y a pas de conflit, nous commit y push les

git commit -m 'merge test branch'
git push

Mais de cette manière, l'historique des changements enregistrés dans la branche de test sera perdu, et il sera difficile pour les autres développeurs de comprendre l'historique du projet dans la branche master.

Donc la meilleure méthode est d'utiliser rebase au lieu de merge (supposons que, pendant ce temps, nous ayons résolu les conflits de branche).

Voici un exemple simple, pour les opérations avancées, veuillez vous référer à http://git-scm.com/book/en/v2/Git-Branching-Rebasing

git checkout master
git pull
git checkout test
git pull
git rebase -i master
git checkout master
git merge test

Oui, lorsque vous aurez terminé les montées, tous les commits de la branche Test seront déplacés vers la tête de la branche Master. L'avantage majeur du rebasage est que vous obtenez un historique linéaire et beaucoup plus propre du projet.

La seule chose à éviter est : ne jamais utiliser rebase sur la branche publique, comme la branche master.

Ne jamais faire d'opérations comme les suivantes :

git checkout master
git rebase -i test

Détails pour https://www.atlassian.com/git/tutorials/merging-vs-rebasing/the-golden-rule-of-rebasing

annexe :

95voto

raylu Points 974

Ni une rebase ni une fusion ne doivent écraser les modifications de quiconque (sauf si vous choisissez de le faire lors de la résolution d'un conflit).

L'approche habituelle lors du développement est la suivante

git checkout master
git pull
git checkout test
git log master.. # if you're curious
git merge origin/test # to update your local test from the fetch in the pull earlier

Quand tu es prêt à fusionner à nouveau dans le master,

git checkout master
git log ..test # if you're curious
git merge test
git push

Si vous avez peur de casser quelque chose sur la fusion, git merge --abort est là pour vous.

Utiliser le push puis le pull comme moyen de fusionner est stupide. Je ne sais pas non plus pourquoi vous poussez test vers origin.

1 votes

Ce processus va augmenter le nombre de commits, chaque fois que vous passez d'une branche à l'autre, vous devez commiter votre branche.

2 votes

Quoi ? Tu veux dire que ça va augmenter le nombre de commits à chaque fois que tu changes de branche ? Ou vous dites qu'à chaque fois que vous changez de branche, vous devez "commiter votre branche" ? Le premier est faux et je ne suis pas sûr de ce que le second signifie.

0 votes

Avant le checkout, vous devez commiter la branche. c'est ce que je veux dire

48voto

moose Points 4945

Je commencerais par rendre la branche à fusionner aussi propre que possible. Exécutez vos tests, assurez-vous que l'état est tel que vous le souhaitez. Nettoyez les nouveaux commits en git squash .

Outre Réponse de KingCrunches je suggère d'utiliser

git checkout master
git pull origin master
git merge --squash test
git commit
git push origin master

Vous avez peut-être fait de nombreux commits dans l'autre branche, qui ne devraient être qu'un seul commit dans la branche maître. Pour garder l'historique des commits aussi propre que possible, vous pouvez vouloir écraser tous vos commits de la branche de test en un seul commit dans la branche principale (voir aussi : Git : Écraser ou ne pas écraser ? ). Ensuite, vous pouvez également réécrire le message de validation en quelque chose de très expressif. Quelque chose qui est facile à lire et à comprendre, sans avoir à creuser dans le code.

edit : Vous pourriez être intéressé par

Donc, sur GitHub, je finis par faire ce qui suit pour une branche de fonctionnalité mybranch :

Recevez les dernières nouvelles d'origine

$ git checkout master
$ git pull origin master

Trouver le hachage de la base de fusion :

$ git merge-base mybranch master
c193ea5e11f5699ae1f58b5b7029d1097395196f

$ git checkout mybranch
$ git rebase -i c193ea5e11f5699ae1f58b5b7029d1097395196f

Maintenant, assurez-vous que seul le premier est pick le reste est s :

pick 00f1e76 Add first draft of the Pflichtenheft
s d1c84b6 Update to two class problem
s 7486cd8 Explain steps better

Choisissez ensuite un très bon message de commit et poussez-le sur GitHub. Faites ensuite la demande de retrait.

Après la fusion de la demande de pull, vous pouvez la supprimer localement :

$ git branch -d mybranch

et sur GitHub

$ git push origin :mybranch

18voto

user1189762 Points 1406

Vieux fil, mais je n'ai pas trouvé à ma façon de le faire. Cela peut être utile pour quelqu'un qui travaille avec rebase et qui veut fusionner tous les commits d'une branche (de fonctionnalité) au-dessus de master. S'il y a un conflit en cours de route, vous pouvez le résoudre pour chaque commit. Vous gardez le contrôle total pendant le processus et pouvez l'interrompre à tout moment.

Mettez à jour le Master et la Branche :

git checkout master
git pull --rebase origin master
git checkout <branch_name>
git pull --rebase origin <branch_name>

Fusionner la branche sur le master :

git checkout <branch_name>
git rebase master

Facultatif : Si vous rencontrez des conflits pendant le rebasement :

D'abord, résoudre le conflit dans le dossier. Ensuite :

git add .
git rebase --continue

Vous pouvez interrompre le rebasement à tout moment avec :

git rebase --abort

Poussez votre branche rebasée :

git push origin <branch_name>

Si cette branche a été poussée avant, vous devez la remplacer par un force push :

git push origin -f <branch_name>

Avant de le faire, vérifiez toujours si votre branche locale actuelle correspond à vos attentes, car le push forcé remplace l'ancienne dans le dépôt distant.

Maintenant, vous avez deux options :

  • A) Créer un PR (par exemple sur GitHub) et le fusionner via l'interface utilisateur.
  • B) Retourner sur la ligne de commande et fusionner la branche dans master

    git checkout master git merge --no-ff <branch_name> git push origin master

C'est fait.

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