web-dev-qa-db-fra.com

Git fusionner le maître en branche de fonctionnalité

Disons que nous avons la situation suivante dans git:

  1. Un référentiel créé:

    mkdir GitTest2
    cd GitTest2
    git init
    
  2. Certaines modifications dans le maître ont lieu et sont validées.

    echo "On Master" > file
    git commit -a -m "Initial commit"
    
  3. Feature1 ramifié hors maître et certains travaux sont effectués:

    git branch feature1
    git checkout feature1
    echo "Feature1" > featureFile
    git commit -a -m "Commit for feature1"
    
  4. Pendant ce temps, un bogue est découvert dans le code principal et une branche de correctif est établie

    git checkout master
    git branch hotfix1
    git checkout hotfix1
    
  5. Le bogue est corrigé dans la branche de correctif logiciel et fusionné dans le maître (peut-être après une révision de demande d'extraction/de code):

    echo "Bugfix" > bugfixFile
    git commit -a -m "Bugfix Commit"
    git checkout master
    git merge --no-ff hotfix1
    
  6. Le développement sur feature1 continue:

    git checkout feature1
    

Maintenant ma question: Dites que j'ai besoin du correctif dans ma branche de fonctionnalité, peut-être parce que le bogue s'y produit également. Comment y parvenir sans dupliquer les commits dans ma branche de fonctionnalités? Je veux éviter d’obtenir deux nouveaux commits sur ma branche de fonctionnalité qui n’ont aucun lien avec l’implémentation de la fonctionnalité. Cela semble particulièrement important pour moi si j'utilise des demandes d'extraction: toutes ces mises à jour seront également incluses dans la demande d'extraction et doivent être examinées bien que cela ait déjà été fait (car le correctif est déjà dans le maître).

Je ne peux pas faire un git merge master --ff-only: "fatal: Impossible d'avancer rapidement, d'abandonner.", Mais je ne suis pas sûr que cela m'aide.

833
theomega

Vous devriez pouvoir rebaser votre branche sur master:

git checkout feature1
git rebase master

Gérer tous les conflits qui surviennent. Quand vous arriverez aux commits avec les corrections de bugs (déjà en master), git dira qu'il n'y a pas eu de changements et qu'ils ont peut-être déjà été appliqués. Vous continuez ensuite la rebase (en ignorant les commits déjà en master) avec

git rebase --skip

Si vous effectuez un git log sur votre branche, vous verrez que la validation du correctif apparaîtra une seule fois et dans la partie principale.

Pour une discussion plus détaillée, consultez la documentation du livre Git sur git rebase ( https://git-scm.com/docs/git-rebase ) qui couvre exactement ce cas d'utilisation. .

================ Modifier pour un contexte supplémentaire ====================

Cette réponse a été fournie spécifiquement pour la question posée par @theomega, en tenant compte de sa situation particulière. Notez cette partie:

Je souhaite éviter les [...] commits sur ma branche de fonctionnalité qui n'ont aucun lien avec la mise en œuvre de la fonctionnalité.

Rebaser sa branche privée sur master est exactement ce qui donnera ce résultat. En revanche, fusionner le maître dans sa branche ferait précisément ce qu'il ne veut pas arriver : l'ajout d'un commit qui n'est pas lié à l'implémentation de la fonctionnalité sur laquelle il travaille via sa branche.

Pour adresser les utilisateurs qui lisent le titre de la question, ignorez le contenu et le contexte de la question, puis ne lisez que la première réponse à l'aveuglette, en supposant qu'il s'appliquera toujours à leur cas d'utilisation (différent), permettez-moi de préciser:

  • ne rebase que les branches privées (c'est-à-dire qu'elles n'existent que dans votre référentiel local et n'ont pas été partagées avec d'autres). Réinitialiser les branches partagées "casserait" les copies que d'autres personnes pourraient avoir.
  • si vous souhaitez intégrer les modifications d'une branche (maître ou autre) à une branche publique (vous avez par exemple poussé la branche à ouvrir une demande d'extraction, mais il existe maintenant des conflits avec maître et vous devez mettre à jour votre branche pour résoudre ces conflits), vous devrez les fusionner (par exemple avec git merge master comme dans la réponse de @ Sven).
  • vous pouvez également fusionner des branches dans vos branches privées locales si tel est votre préférence, mais sachez que cela entraînera des validations "étrangères" dans votre branche.

Enfin, si vous n'êtes pas satisfait du fait que cette réponse ne convient pas à votre situation, même si c'était pour @theomega, l'ajout d'un commentaire ci-dessous ne sera pas particulièrement utile: je ne contrôle pas la réponse sélectionnée, seul @theomega le fait.

512
David Sulc

Comment fusionner la branche principale dans la branche fonctionnelle? Facile:

git checkout feature1
git merge master

Il est inutile de forcer une fusion rapide vers l'avant ici, car cela ne peut pas être fait. Vous avez engagé à la fois la branche de fonctionnalité et la branche principale. L'avance rapide est impossible maintenant.

Regardez gitflow . C'est un modèle de branchement pour git qui peut être suivi, et vous l'avez déjà fait inconsciemment. C'est également une extension de git qui ajoute des commandes pour les nouvelles étapes du flux de travail qui effectuent automatiquement des tâches que vous auriez sinon besoin de faire manuellement.

Alors, qu'avez-vous fait dans votre flux de travail? Vous avez deux branches avec lesquelles travailler, votre branche feature1 est essentiellement la branche "develop" du modèle gitflow.

Vous avez créé une branche de correctif à partir de maître et l'avez fusionnée. Et maintenant tu es coincé.

Le modèle gitflow vous demande de fusionner également le correctif avec la branche de développement, qui est "feature1" dans votre cas.

Donc, la vraie réponse serait:

git checkout feature1
git merge --no-ff hotfix1

Cela ajoute toutes les modifications apportées à l'intérieur du correctif à la branche de fonctionnalité, mais UNIQUEMENT ces modifications. Ils peuvent entrer en conflit avec d'autres modifications de développement dans la branche, mais ils ne le seront pas avec la branche maître si vous fusionnez la branche d'objet en mode maître.

Soyez très prudent avec rebasing. Ne rebasez que si les modifications que vous avez apportées sont restées locales dans votre référentiel, par exemple. vous n'avez pas poussé de branches dans un autre référentiel. Rebaser est un excellent outil pour organiser vos commits locaux dans un ordre utile avant de le propager dans le monde, mais rebasonner ensuite gâchera les choses pour les git novices comme vous.

984
Sven

En vous basant sur cet article vous devriez:

  • créer une nouvelle branche basée sur la nouvelle version de master

    git branch -b newmaster

  • fusionner votre ancienne branche avec une nouvelle

    git checkout newmaster

  • résoudre les conflits sur la nouvelle branche de fonctionnalité

Les deux premières commandes peuvent être combinées à git checkout -b newmaster

De cette façon, votre historique reste clair car vous n'avez pas besoin de fusions en arrière. Et vous n'avez pas besoin d'être si prudent car vous n'avez pas besoin de git rebase

61
zimi

La réponse de Zimi décrit ce processus en général. Voici les détails:

1) Créez et basculez vers une nouvelle branche. Assurez-vous que la nouvelle branche est basée sur master afin d’inclure les correctifs récents.

git checkout master
git branch feature1_new
git checkout feature1_new

# Or, combined into one command:
git checkout -b feature1_new master

2) Après avoir basculé vers la nouvelle branche, fusionnez les modifications de votre branche de fonctionnalité existante. Cela ajoutera vos commits sans dupliquer les commits de correctifs.

git merge feature1

3) Sur la nouvelle branche, résolvez les conflits éventuels entre votre fonction et la branche principale.

Terminé! Maintenant, utilisez la nouvelle branche pour continuer à développer votre fonctionnalité.

23
jkdev

Voici un script que vous pouvez utiliser pour fusionner votre branche principale dans votre branche actuelle.

Le script effectue les opérations suivantes:

  • Bascule vers la branche principale
  • Tire la branche principale
  • Revient à votre branche actuelle
  • Fusionne la branche principale dans votre branche actuelle

Enregistrez ce code sous forme de fichier de commandes (.bat) et placez le script n'importe où dans votre référentiel. Puis cliquez dessus pour le lancer et vous êtes prêt.

:: This batch file pulls current master and merges into current branch

@echo off

:: Option to use the batch file outside the repo and pass the repo path as an arg
set repoPath=%1
cd %repoPath%

FOR /F "tokens=*" %%g IN ('git rev-parse --abbrev-ref HEAD') do (SET currentBranch=%%g)

echo current branch is %currentBranch%
echo switching to master
git checkout master
echo.
echo pulling Origin master
git pull Origin master
echo.
echo switching back to %currentBranch%
git checkout %currentBranch%
echo.
echo attemting merge master into %currentBranch%
git merge master
echo.
echo script finished successfully
PAUSE
9
Aaron M.

Vous pourrez peut-être effectuer un "tri sélectif" pour extraire les exacts commit (s) dont vous avez besoin dans votre branche de fonctionnalité.

Faites un git checkout hotfix1 pour accéder à la branche du correctif 1. Ensuite, faites un git log pour obtenir le hachage SHA1 (grande séquence de lettres et de chiffres aléatoires identifiant de manière unique un commit) du commit en question. Copiez cela (ou les 10 premiers caractères environ).

Ensuite, git checkout feature1 pour revenir à votre branche de fonctionnalité.

Ensuite, git cherry-pick <the SHA1 hash that you just copied>

Cela entraînera cette validation et niquement cette validation dans votre branche de fonctionnalité. Ce changement sera dans la branche - vous venez de le "sélectionner". Ensuite, reprenez le travail, éditez, commettez, Push, etc. au contenu de votre coeur.

Lorsque, éventuellement, vous effectuez une autre fusion d'une branche dans votre branche de fonctionnalités (ou vice-versa), git reconnaîtra que vous avez déjà fusionné dans cette particularité commit, sachez que cela n'a pas été le cas. pour le faire à nouveau, et juste "sauter" sur elle.

9
Bob Gilmore