62 votes

git: fusionner deux branches: quelle direction?

Nous avons la situation suivante:

             A --- B --- C --- ... --- iphone
           /
  ... --- last-working --- ... --- master

Entre le dernier et l'iPhone, 32 commits ont été faites. Entre le dernier et le maître, beaucoup de validations ont été faites.

Ce que je veux maintenant, c'est une nouvelle branche où j'ai l'iphone et de l'actuel maître fusionnés ensemble. Et quelque temps plus tard, ce devrait être fusionné dans le maître.

Tout d'abord, j'ai prévu de faire:

git checkout iphone -b iphone31
git merge master

Mais ensuite j'ai pensé, si il serait mieux de le faire:

git checkout master -b iphone31
git merge iphone

Maintenant, je me demande. Quelle serait la différence dans le résultat? Serait la fusion se comportent-ils différents?

J'ai déjà essayé les deux et comme je l'ai prévu, j'ai eu beaucoup de conflits, car l'iphone est vraiment vieux par rapport à maîtriser. Maintenant je m'interroge sur la meilleure façon de les fusionner.

Peut-être même de commencer avec le maître et la fusion de chaque commit unique de l'iphone en il serait plus facile? Comme cela:

git checkout master -b iphone31
git merge A
git merge B
git merge C
...
git merge iphone

À la fin, lorsque cette opération est effectuée (c'est à dire tous les conflits sont résolus et il fonctionne), je veux faire ceci:

git checkout master
git merge iphone31

43voto

hlovdal Points 11039

Concernant les solutions de rechange

git checkout iphone -b iphone31
git merge master

et

git checkout master -b iphone31
git merge iphone

ils auront la même facilité ou la difficulté, c'est comme arguant qu'un verre est à moitié plein ou à moitié vide.

L'arbre de Version de la perception

La façon dont nous regardons la version arbres sont en quelque sorte nos arbitraire de la perception. Disons que nous avons une version de l'arbre comme suit:

    A----------+
    |          |
    |          |
   \_/        \_/
    B          X
    |          |
    |          |
   \_/        \_/
    C          Y
    |
    |
   \_/
    D
    |
    |
   \_/
    E

Et disons que nous voulons faire une nouvelle version Z extrait de Y' sur la base des changements de C à E, mais pas y compris les modifications apportées à partir de De A à C.

"Oh, ça va être difficile, car il n'y a pas de point de départ commun." Et bien pas vraiment. Si on se contente de placer les objets un peu différemment dans le graphique de mise en page comme ceci

      /
    C+---------+
    | \        |
    |          |
   \_/         |
    D          B
    |         / \
    |          |
   \_/         |
    E          A
               |
               |
              \_/
               X
               |
               |
              \_/
               Y

maintenant, les choses sont en train de regarder prometteur. Notez que je n'ai pas changé toute relation envoyé ici, les flèches pointent tous de la même façon que dans l'image précédente et la version A est toujours le socle commun. Seule la mise en page est modifiée.

Mais maintenant trivial d'imaginer un autre arbre

    C'---------+
    |          |
    |          |
   \_/        \_/
    D          B'
    |          |
    |          |
   \_/        \_/
    E          A
               |
               |
              \_/
               X
               |
               |
              \_/
               Y

d'où la tâche serait de fusionner la version E normalement.

De sorte que vous pouvez fusionner tout ce que vous voulez, la seule chose qui influence la facilité ou la difficulté est l'ensemble des modifications effectuées entre où vous sélectionnez un point de départ ou de base commune et où vous fusionner pour. Vous n'êtes pas limité à l'aide du point de départ naturel de la votre gestion des versions de l'outil de suggérer.

Cela pourrait ne pas être simple avec certains systèmes de contrôle de version/outils, mais si tout le reste échoue, il n'est rien qui vous empêche de le faire manuellement par de vérifier la version C et enregistrez le fichier fichier1, de vérifier la version E et enregistrez le fichier en tant que fichier2, de vérifier la version Y et enregistrez le fichier en tant que fichier3 et exécutez kdiff3 -o merge_result file1 file2 file3.

Réponse

Maintenant, pour votre situation spécifique, il est difficile de dire exactement ce qu' stratégie qui permettra de produire le moins de problèmes, mais si il y a beaucoup de changements qui créent une sorte de conflit, il est probablement plus facile de diviser et fusionner les petites pièces.

Ma suggestion serait que puisqu'il y a 32 s'engage entre la dernière et l'iphone, vous pourriez par exemple commencer par une ramification de maître, et fusion dans les 16 premiers commits. Si cela s'avère être trop de difficultés, de revenir et d'essayer de fusionner les 8 premiers commits. Et ainsi de suite. Dans le pire des cas, en fin de fusion de chacun des 32 commet un par un, mais il serait sans doute plus facile que d'avoir à gérer tous les le cumul des conflits en une seule opération de fusion (et dans ce cas, vous travaillez avec un vraiment divergentes de la base de code).

Conseils:

Tirage sur papier une version de l'arbre et de la note avec les flèches de ce que vous voulez de fusion. Rayez les choses comme elles le sont en fait si vous fractionnez le processus en plusieurs étapes. Cela vous donnera une image plus claire de ce que vous voulez à atteindre, ce que vous avez fait et ce qui est à gauche.

Je peux vraiment recommander KDiff3, c'est un excellent diff/merge tool.

6voto

seanhodges Points 8005

La meilleure approche dépend vraiment de savoir si d'autres personnes ont des copies distantes de votre code. Si le maître de la branche est uniquement en local sur votre machine, vous pouvez utiliser la commande rebase de manière interactive appliquer les commits de la branche en master:

git checkout master -b iphone-merge-branch
git rebase -i iphone

Notez que cela modifie la validation de l'histoire de votre nouvel iphone-fusion-branche de la branche, ce qui peut causer des problèmes pour quelqu'un d'autre en essayant de tirer vos changements dans leur commande plus tard. En revanche, la commande de fusion s'applique les modifications en tant que nouveau commit, ce qui est plus sûr lors d'une collaboration, car il n'affecte pas l'histoire de la branche. Voir cet article pour quelques conseils utiles sur l'utilisation de git rebase.

Si vous avez besoin de garder votre s'engager dans l'histoire de la synchronisation, vous êtes mieux de l'exécution d'une fusion. Vous pouvez utiliser git mergetool de manière interactive résoudre les conflits de un-à-un à l'aide d'un visual diff outil (un tutoriel sur ce qui peut être trouvé ici):

git checkout master -b iphone-merge-branch
git merge iphone
git mergetool -t kdiff3

Une troisième option, si vous voulez un contrôle absolu sur le processus, serait d'utiliser git cherry-pick. Vous pouvez utiliser gitk (ou de votre favori de l'histoire de la visionneuse) pour afficher la validation des hachages dans l'iphone branche, notez-les, et cerise choisir individuellement dans la fusion de la branche de fixation des conflits, comme vous allez. Une explication de ce processus peut être trouvé ici. Ce processus sera le plus lent, mais qui pourrait être la meilleure option de repli si les autres méthodes ne fonctionnent pas:

gitk iphone
<note down the 35 commit SHA hashes in this branch>
git checkout master -b iphone-merge-branch
git cherry-pick b50788b
git cherry-pick g614590
...

2voto

ardsrk Points 1393

Vous dites:

iphone branche est très vieux par rapport à la maîtrise de

Voulez-vous vraiment à fusionner les deux formant une nouvelle branche?

Le but du maître et de l'iphone branches aurait été très différent ( car l'iphone est très ancienne ). Une nouvelle branche de la fusion de l'iphone avec un ancêtre de maître serait mieux? Pensez à ce sujet.

Je vous recommande fortement de lire avec Plaisir et fusionne les fins de branches.

Après la lecture de cet article, si vous vous sentez toujours que vous souhaitez fusionner iphone et capitaine @seanhodges explique comment traiter les conflits de vraiment bien.

1voto

Thinkeye Points 93

Vous pouvez faire une sauvegarde locale de votre travail avant d'expérimenter, de sorte que vous pouvez redémarrer, si vous arrêtez de comprendre ce qui est arrivé.

Effectuer une sauvegarde de la branche de votre travail pour ne pas le perdre lors de rebase, si vous voulez le garder pour référence.

git checkout iphone -b iphone_backup

Créer une nouvelle branche à partir de maître

git checkout master -b iphone31

puis rebase sur le dessus de cela.

git rebase -i --onto iphone31 iphone

Sean ci-dessus est correcte sur rebase l'application de l'un s'engager à la fois. Mais ne vous inquiétez pas sur les commits de la branche vous rebase sur, ils ne vont pas être changé. Rebase, qui met les nouvelles (adapté) s'engage au-dessus d'eux. Alors que fait un commit à un moment vous avez un meilleur contrôle sur les conflits. Ce qui est important, cependant, vous devez rebase votre travail sur le dessus du maître et non pas vice versa, si l'histoire du maître ne changera pas.

Alternativement, vous pouvez le faire seul

git rebase -i master iphone

si vous n'avez pas de soins sur la sauvegarde de l'iphone branche. Regarder dans rebase la documentation pour plus de détails et des solutions de rechange http://git-scm.com/docs/git-rebase.

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