web-dev-qa-db-fra.com

Branchement et fusion de base Git / Sourcetree

Alerte question débutant !!! Je commence à peine à utiliser Git, et en particulier Sourcetree qui semble être une bonne application pour le visualiser. Lors de mon premier test, cela s'est plutôt bien passé, en se ramifiant et en fusionnant (voir le diagramme du haut). Je sais que cette structure signifie que j'utilise la branche développement et master dans le mauvais sens, mais c'est bien parce qu'au moins cela a fonctionné.

Lors de mon deuxième essai, je n'arrivais pas à visualiser les branches, même si le travail était en cours dans les deux, elles semblent apparaître dans une seule branche (avec une note `` 7 à l'avance ''), et lorsque j'essaie de fusionner rien ne semble arriver. Espérons que la deuxième capture d'écran soit suffisante pour que quelqu'un me dise ce qui se passe ici? Sinon, je vais essayer de donner plus d'informations.

Je suis juste en train de jouer pour le moment, donc toujours à maîtriser le flux de travail approprié, juste à essayer de faire en sorte que les actions de branchement et de fusion de base se déroulent de manière cohérente via Sourcetree. Toute aide serait appréciée.

enter image description here

41
Chris

Dans la deuxième image, il y a des branches. Localement, vous avez 2 branches, master & develop. Les deux branches reposent cependant sur le même commit. Si vous voulez 'voir les branches' comme dans la première image, vous pouvez faire un commit sur develop, cependant le graphique apparaîtra toujours linéaire. Vous pourrez fusionnerdévelopper en master à ce stade si vous le souhaitez.

Si vous voulez voir le graphique diverger, essayez également de valider master. Ensuite, vous commencerez à voir quelque chose de plus semblable à la première image.

Pour avoir une idée du fonctionnement de git avec un programme de visualisation comme celui-ci, je vous suggère de faire des actions comme je l'ai suggéré ci-dessus, et de jeter un œil au graphique à chaque étape intermédiaire.

13
quickshiftin

Il se passe quelques choses ici. Tout d'abord, il est utile de comprendre que les branches dans Git ne sont en réalité que des "étiquettes" qui sont collées à une validation particulière, et qui seront déplacées automatiquement lorsque vous vous engagez dans la branche; Git créera le nouveau commit, avec un nouveau hachage de commit, et mettra à jour la branche/étiquette pour pointer vers le nouveau commit. (Vous pourriez vous demander, en quoi est-ce différent des balises, alors? Une balise est collée au même commit et ne recevra pas de mises à jour lorsque vous appelez git commit.)

Lorsque vous créez une nouvelle branche, tout ce qui se passe, c'est que Git crée une nouvelle étiquette, pointant vers le même commit sur lequel vous étiez. Ce n'est que lorsque vous créez un nouveau commit alors que cette nouvelle branche est extraite que vous verrez la nouvelle branche diverger de l'autre branche.

La vraie confusion commence lorsque vous recommencez à fusionner les branches, et cela est largement dû à une chose étrange que Git appelle la "fusion rapide", ce qu'elle fait par défaut . Prenons votre deuxième exemple et imaginons que votre master et votre développement sont là où étaient à l'origine Origin/master et Origin/develop:

Simple linear branching example

Lorsque vous demandez à Git de fusionner une branche dans une autre, Git ira trouver ce qu'il doit faire pour obtenir la différence entre ces branches dans la branche cible. Imaginons que vous souhaitiez fusionner les modifications que vous avez apportées pour devenir master, vous dites donc à git:

$ git checkout master
$ git merge develop

Git regardera les branches et verra que develop est juste en avance sur master de quelques commits, mais il n'y a rien de plus compliqué que ça. Ainsi, il effectuera une fusion "d'avance rapide", en prenant simplement le label principal et en le collant au commit où pointe le développement. Mission accomplie, des changements qui n'étaient en cours qu'auparavant sont désormais également en cours.

Si chaque branche a des commits supplémentaires, comme dans votre premier exemple juste avant de fusionner master en develop, "quelque chose de plus compliqué" se passe . Vous avez fait un commit sur master, puis vous avez développé un checkout git, vous avez fait un commit là-bas et puis vous avez demandé à Git de fusionner le master dans develop. Git ne peut plus "tricher" en déplaçant simplement les étiquettes de branche. Il devra trouver comment unifier les changements des deux branches en un seul état des fichiers sous son contrôle (supposons, pour l'instant, qu'il est toujours en mesure de le faire, ce qui n'est pas si loin de la vérité; son Si c'est impossible, vous avez un conflit de fusion, ce qui n'est vraiment pas aussi grave qu'il y paraît).

Le nouveau contenu, après la fusion, ne sera ni le dernier état de la première branche, ni l'état de la deuxième branche. Il doit donc être représenté par un tout nouveau commit, ce que vous voyez en haut de votre premier exemple; Git a créé ce qu'il appelle un "commit de fusion" pour représenter le nouvel état avec les modifications de chaque branche fusionnées en un seul état.

Enfin, vous pouvez forcer Git à toujours créer un commit de fusion, même s'il n'est strictement, techniquement, pas nécessaire. Dans la ligne de commande, vous pouvez le faire avec l'indicateur --no-ff, sans avance rapide. Les clients graphiques auront une case à cocher qui accomplira la même chose (dans SourceTree, il est actuellement étiqueté "Créer un commit même si la fusion est résolue via l'avance rapide"). Beaucoup (y compris moi-même) recommandent de fusionner avec --no-ff, car de cette façon, l'acte de fusion est toujours enregistré dans l'histoire, indépendamment des technicallités comme s'il serait techniquement possible de simplement déplacer les pointeurs de branche.

4
Eelke Blok

Je viens de rencontrer ce même problème et j'ai découvert qu'il y a un paramètre dans SourceTree pour "Ne pas avancer rapidement lors de la fusion, toujours créer un commit". Assurez-vous que c'est coché et vous verrez la structure de la branche à partir d'eux.

Ce paramètre se trouve sur l'onglet Git dans les préférences.

2
Jason Alford

Vous pouvez empêcher les branches de disparaître définitivement dans l'arbre source en activant "Ne pas avancer rapidement lors de la fusion, toujours créer un commit" dans Outils/Options .

Disabling fast-forward when merging permanently in Source Tree

Si vous souhaitez décider pour chaque opération de fusion, il existe une option " Créer un nouveau commit même si une avance rapide est possible " dans la boîte de dialogue Fusionner .

Disable fast-forward when merging during each merge operation in Source Tree

Je suggère également de se référer Eelke Blok 's réponse pour les détails techniques.

1
Guney Ozsan