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


2105

Une nouvelle branche de masterest créée, nous l'appelons test.

Il existe plusieurs développeurs qui s'engagent masterou créent d'autres branches et fusionnent plus tard master.

Disons que le travail testprend plusieurs jours et que vous souhaitez rester constamment à testjour avec des commits à l'intérieur master.

Je ferais git pull origin masterde 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 testest terminé et je suis prêt à le fusionner master. Voici les deux façons dont je peux penser:

UNE:

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, --rebasecar d'après ma compréhension, rebase récupérera les modifications masteret empilera les miennes en plus, ce qui pourrait écraser les modifications apportées par d'autres personnes.

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

Le but dans tout cela est de garder ma testbranche à jour avec les choses qui se passent masteret plus tard je pourrais les fusionner pour masterespérer garder la chronologie aussi linéaire que possible.


18
non .. rebase jamais écraser, il essaie juste de réaliser une histoire plus propre. par rattacher (ou faux) l'histoire au point tardif du maître
Junchen Liu

7
rebase n'écrase pas vos commits. Il annule vos validations, applique les validations de la branche principale à votre branche de test, puis applique à nouveau vos validations au test.
zundi

Réponses:


2995

Comment je ferais ça

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

Si j'ai une branche locale d'une télécommande, je ne me sens pas à l'aise pour fusionner d'autres branches que celle-ci avec la télécommande. De plus, je ne pousserais pas mes modifications, jusqu'à ce que je sois satisfait de ce que je veux pousser et aussi je ne pousserais pas du tout les choses, qui ne sont que pour moi et mon référentiel local. Dans votre description, il semble que ce testsoit uniquement pour vous? Donc pas de raison de le publier.

git essaie toujours de respecter les vôtres et les autres, et il en sera de même --rebase. Je ne pense pas pouvoir l'expliquer correctement, alors jetez un œil au livre Git - Rebasing ou git-ready: Intro into rebasing for a little description. C'est une fonctionnalité assez cool


2
git merge testme donne fatal: 'test' does not point to a commit. Je dois rechercher git logle point de validation sur la branche de test, revenir à la branche principale, puis le faire git merge 0f37d3154abbf52a4cbbbb5109f08af6a7567234.
Duncanmoo

17
@Duncanmoo Eh bien, bien sûr, la branche testdoit exister. Bien sûr, vous pouvez utiliser le hachage de validation à 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 hachage HEADde la branche.
KingCrunch

44
@shanyangqu Pour obtenir les dernières modifications de la télécommande. Si vous travaillez seul et avec un seul système, il n'y a aucun 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 repousser votre fusion (la 4ème étape). La seule solution est maintenant de fusionner votre maître local dans le maître des télécommandes, ce qui se termine par un commit de fusion assez "laid fusionné maître en origine / maître". C'est donc toujours une bonne idée de faire un pull avant la fusion
KingCrunch

7
"Dans votre description, il semble que ce test ne soit que pour vous? Donc, aucune raison de le publier." Vous voudrez peut-être pousser votre branche locale vers un serveur si, par exemple, ce serveur fournit une sauvegarde contre la défaillance de votre lecteur local ou si vous n'avez pas d'autre moyen de faire une sauvegarde.
Eric

5
"... Je ne voudrais pas non plus pousser mes modifications, jusqu'à ce que je sois satisfait de ce que je veux pousser ..." pourquoi ne pas pousser pour le plaisir d'avoir votre code sauvegardé, au cas où vos machines locales mourraient et des jours d'efforts sont partis?
Rich Stone

400

C'est 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 présente deux problèmes :

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

  2. Il "resserrerait" toutes les validations de test en une seule validation de fusion sur le maître; c'est-à-dire sur la branche principale, nous ne pouvons pas voir tous les journaux des modifications de la branche de test.

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

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

Testez mergeavant commit, évitez une validation rapide par --no-ff,

En cas de conflit, nous pouvons exécuter git statuspour vérifier les détails des conflits et essayer de résoudre

git status

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

git commit -m 'merge test branch'
git push

Mais cette façon perdra l'historique des modifications consigné dans la branche de test, et il serait difficile pour les autres développeurs de comprendre l'historique du projet.

Donc, la meilleure méthode est que nous devons utiliser à la rebaseplace de merge(supposons, quand dans ce temps, nous avons résolu les conflits de branche).

Voici un exemple simple, pour les opérations avancées, veuillez vous reporter à 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 avez terminé les tiges, toutes les validations de la branche Test seront déplacées vers la tête de la branche Master. Le principal avantage du rebasage est que vous obtenez un historique de projet linéaire et beaucoup plus propre.

La seule chose que vous devez éviter est: ne jamais utiliser rebasesur une branche publique, comme la branche principale.

Ne faites jamais 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:


4
Je suis d'accord pour rebaser la branche de test pour une fusion ultérieure dans master est la voie à suivre. Même les autres réponses sont correctes, cela gardera l'historique des changements de test de branche dans la tête du maître car l'auther mentionne "vous obtenez un projet de doublure et beaucoup plus propre" qui est l'objectif du système de contrôle de version.
le0diaz

16
L'énoncé «ce n'est pas une voie de sécurité, car nous ne savons pas s'il y a des conflits entre la branche de test et la branche principale» n'est pas vrai: on peut toujours abandonner la fusion. Et même s'il n'y a pas de conflits, vous pouvez toujours annuler le dernier commit local tant qu'il n'est pas poussé. Sans une bonne compréhension de git, certaines choses peuvent sembler un peu effrayantes ou peu claires, mais «dangereux» est tout simplement incorrect. Veillez à ne pas confondre les autres avec des informations incorrectes.
Paul van Leeuwen

4
d'accord avec @PaulvanLeeuwen, lorsque vous fusionnez la branche de test en maître, vous serez averti des conflits, et c'est là que vous interviendrez et fusionnerez les modifications. Une fois que vous avez terminé, vous allez valider la fusion et repousser. Si vous regrettez ou ne parvenez pas à le fusionner correctement, vous pouvez toujours jeter votre travail et retirer du maître. Ce n'est donc certainement pas dangereux ..
Juan

3
pourquoi rebaser -i?
MushyPeas

8
Le rebasage est intrinsèquement plus dangereux que la fusion. Il est faux de proposer le rebasage comme une option plus sûre de fusionner. La refondation est une stratégie valable, mais elle comporte plus d'avertissements dont l'utilisateur doit se méfier.
Ikke

90

Ni un rebase ni une fusion ne doivent remplacer 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

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

Lorsque vous êtes prêt à fusionner de nouveau en maître,

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

Si vous craignez de casser quelque chose lors de la fusion, git merge --abortest là pour vous.

Utiliser push puis pull comme moyen de fusion est idiot. Je ne sais pas non plus pourquoi vous poussez le test vers l'origine.


1
Ce processus augmentera le nombre de validations, chaque fois que vous basculez entre les branches, vous devez valider votre branche.
iBug

2
Quelle? Êtes-vous en train de dire que cela augmentera le nombre de validations à chaque changement de succursale? Ou dites-vous que chaque fois que vous changez de branche, vous devez "valider votre branche"? Le premier est faux et je ne sais pas ce que le second signifie.
raylu

avant le paiement, vous devez valider la branche. c'est ce que je dis
iBug

11
Vous ne le faites pas: c'est (une des choses) git stashest pour.
msanford

1
Ou vous pouvez modifier votre dernier commit (dans la branche locale) et le rendre parfait avant de pousser.
whihathac

42

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

Outre la 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 effectué plusieurs validations dans l'autre branche, qui ne devrait être qu'une seule validation dans la branche principale. Pour garder l'historique des validations aussi propre que possible, vous voudrez peut-être écraser toutes vos validations de la branche de test en une seule validation dans la branche principale (voir aussi: Git: squash ou pas squash? ). Ensuite, vous pouvez également réécrire le message de validation en quelque chose de très expressif. Quelque chose de facile à lire et à comprendre, sans creuser dans le code.

modifier: Vous pourriez être intéressé par

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

Obtenez les dernières informations sur l'origine

$ git checkout master
$ git pull origin master

Trouvez le hachage de base de fusion:

$ git merge-base mybranch master
c193ea5e11f5699ae1f58b5b7029d1097395196f

$ git checkout mybranch
$ git rebase -i c193ea5e11f5699ae1f58b5b7029d1097395196f

Assurez-vous maintenant 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

Ensuite, choisissez un très bon message de validation et envoyez-le à GitHub. Faites ensuite la demande de tirage.

Après la fusion de la demande d'extraction, vous pouvez la supprimer localement:

$ git branch -d mybranch

et sur GitHub

$ git push origin :mybranch

" qui ne devrait être qu'un seul commit dans la branche master ", enfin pas nécessairement; vous pouvez wekk vouloir garder l'histoire
Cocowalla

Sûr. Mais alors n'écrasez pas les commits
Martin Thoma

Je pense que le premier parent semble être la meilleure solution. davidchudzicki.com/posts/first-parent
bkribbs

7

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 veut fusionner toutes les validations d'une branche (fonctionnalité) au-dessus de master. S'il y a un conflit sur le chemin, vous pouvez les résoudre pour chaque commit. Vous gardez un contrôle total pendant le processus et pouvez abandonner à tout moment.

Obtenez le Master et la branche à jour:

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

Fusionner la branche au-dessus du maître:

git checkout <branch_name>
git rebase master

Facultatif: si vous rencontrez des conflits pendant la rebase:

Tout d'abord, résolvez le conflit dans le fichier. Alors:

git add .
git rebase --continue

Poussez votre branche rebasée:

git push origin <branch_name>

Maintenant, vous avez deux options:

  • A) Créez un PR (par exemple sur GitHub) et fusionnez-le via l'interface utilisateur
  • B) Revenez sur la ligne de commande et fusionnez la branche en maître
git checkout master
git merge --no-ff <branch_name>
git push origin master

Terminé.


6

C'est le flux de travail que j'utilise dans mon travail avec l'équipe. Le scénario est tel que vous l'avez décrit. Tout d'abord, lorsque j'ai fini de travailler, testje rebase avec master pour récupérer tout ce qui a été ajouté à master pendant le temps que je travaille sur la testbranche.

git pull -r upstream master

Cela va tirer les modifications vers master depuis que vous avez forké la testbranche et les appliquer, puis appliquez les modifications que vous avez apportées pour tester "en plus" de l'état actuel de master. Il peut y avoir des conflits ici, si les autres personnes ont apporté des modifications aux mêmes fichiers que vous avez modifiés dans le test. S'il y en a, vous devrez les corriger manuellement et valider. Une fois que vous avez fait cela, vous pourrez passer à la branche principale et fusionner testsans problème.


3
git checkout master
git pull origin master
# Merge branch test into master
git merge test

Après la fusion, si le fichier est modifié, lorsque vous le fusionnerez, il résultera d'une erreur de «résolution de conflit»

Donc, vous devez d'abord résoudre tous vos conflits, vous devez à nouveau valider toutes vos modifications, puis pousser

git push origin master

C'est mieux de faire qui a fait des changements dans la branche de test, car il savait quels changements il avait faits.


3

J'utiliserais la méthode de rebase. Principalement parce qu'il reflète parfaitement votre cas sémantiquement, c'est-à-dire. ce que vous voulez faire, c'est actualiser l'état de votre branche actuelle et "faire semblant" comme si elle était basée sur la dernière.

Donc, sans même vérifier master, je voudrais:

git fetch origin
git rebase -i origin/master
# ...solve possible conflicts here

Bien sûr, le simple fait de récupérer à partir de l'origine ne rafraîchit pas l'état local de votre master(car il n'effectue pas de fusion), mais cela convient parfaitement à notre objectif - nous voulons éviter de basculer, pour gagner du temps.


2

La réponse de @ KingCrunch devrait fonctionner dans de nombreux cas. Un problème qui peut survenir est que vous pouvez être sur une machine différente qui doit tirer la dernière version du test. Donc, je recommande d'abord de tirer le test. La révision ressemble à ceci:

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

0

Vous devez faire extraire la branche pour tirer, car tirer signifie fusionner dans le maître, et vous avez besoin d'un arbre de travail pour fusionner.

git checkout master
git pull

Pas besoin de vérifier d'abord; rebaser fait la bonne chose avec deux arguments

git rebase master test  

git checkout master
git merge test

git push par défaut pousse toutes les branches qui existent ici et sur la télécommande

git push
git checkout test

0

Comme le titre l'indique "Best way", je pense que c'est une bonne idée de considérer la stratégie de fusion de patience .

De: https://git-scm.com/docs/merge-strategies

Avec cette option, «fusion-récursif» passe un peu plus de temps pour éviter les erreurs qui se produisent parfois en raison de lignes de correspondance sans importance (par exemple, les accolades de fonctions distinctes). Utilisez-le lorsque les branches à fusionner ont divagué de manière extravagante. Voir aussi git-diff [1] --patience.

Usage:

git fetch
git merge -s recursive -X patience origin/master

Git Alias

J'utilise toujours un alias pour cela, par exemple exécuter une fois:

 git config --global alias.pmerge 'merge -s recursive -X patience'

Maintenant, vous pouvez faire:

git fetch
git pmerge origin/master

0

C'est de GitLab: Suivez simplement les instructions:

entrez la description de l'image ici


0

Je répondrai selon les branches de développement et de fonctionnalité,

si vous êtes sur une branche de fonctionnalité et devez la mettre à jour avec develop, utilisez les commandes ci-dessous: git checkout develop git pull git checkout feature / xyz git merge develop

Maintenant que votre fonctionnalité est mise à jour avec develop, vous pouvez pousser vos modifications.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.