Recherche de site Web

Expliquer les branches Git avec une analogie LEGO


Utilisez cette analogie LEGO utile pour comprendre pourquoi il est important de créer une branche dans Git.

Créer une nouvelle branche dans un référentiel de code est une tâche assez courante lorsque l'on travaille avec Git. C'est l'un des principaux mécanismes permettant de séparer les modifications non liées les unes des autres. C'est aussi très souvent le désignateur principal de ce qui est fusionné dans la branche principale.

Sans branches, soit tout devrait être sélectionné, soit tout votre travail serait fusionné efficacement sous la forme d'un rebase écrasé. Le problème est que les branches héritent du travail de la branche à partir de laquelle elles sont dérivées, ce qui peut vous amener à pousser accidentellement des validations que vous n'aviez jamais prévu d'être dans votre nouvelle branche.

La solution est de toujours débrancher du main (sauf si vous avez l'intention de ne pas le faire). C'est une règle facile à énoncer, mais malheureusement, elle est tout aussi facile à oublier. Il peut donc être utile d'examiner le raisonnement qui se cache derrière cette règle.

Une branche n'est pas un dossier

Il est naturel de considérer une branche Git comme un dossier.

Ce n'est pas.

Lorsque vous créez une branche, vous ne créez pas un environnement propre, même si cela semble être le cas. Une branche hérite de toutes les données contenues dans son parent. Si la branche parent est la branche principale, alors votre nouvelle branche contient l'historique commun de votre projet. Mais si la branche parent est une autre branche hors de main, alors votre nouvelle branche contient l'historique de main plus l'historique de l'autre branche. Je pense souvent en termes de briques LEGO, alors voici un exemple visuel qui n'est pas l'un de ces graphiques de nœuds Git complexes (mais qui l'est en fait, secrètement).

Disons que votre branche principale est une plaque LEGO.

(Seth Kenlon CC BY-SA 4.0)

Lorsque vous créez une branche hors de main, vous ajoutez une brique. Supposons que vous ajoutiez une branche appelée blue.

(Seth Kenlon BY-SA 4.0)

La branche blue contient l'historique de la plaque de base ainsi que tout le travail que vous effectuez sur blue. Dans le code, voici ce qui s'est passé jusqu'à présent :

$ git branch
* main
$ git checkout -b blue

Branche d'une succursale

Si vous créez encore une autre branche alors que vous êtes toujours dans votre branche blue, alors vous construisez au-dessus de main ainsi que de blue. . Supposons que vous créiez une branche appelée red parce que vous souhaitez commencer à créer une nouvelle fonctionnalité.

(Seth Kenlon CC BY-SA 4.0)

Il n'y a rien de mal en soi à cela, tant que vous comprenez que votre branche red est construite sur blue. Tout le travail que vous avez effectué dans la branche bleu existe également en rouge. Tant que vous ne souhaitez pas que red soit un nouveau départ contenant uniquement l'historique de votre branche main, c'est une méthode parfaitement acceptable de construire votre dépôt. Sachez cependant que le propriétaire du projet n'est pas en mesure, par exemple, d'accepter les modifications rouges sans également accepter un ensemble de modifications bleues, du moins pas sans passer par à beaucoup d'ennuis.

Pause propre

Si ce que vous voulez réellement faire est de développer bleu et rouge en tant que fonctionnalités distinctes afin que le propriétaire du projet puisse choisir de fusionner l'une et pas l'autre, alors vous avez besoin des deux. les branches doivent toutes deux être basées uniquement sur main. C'est facile à faire. Il vous suffit de commencer par extraire la branche main, puis de créer votre nouvelle branche à partir de là.

$ git branch
* blue
main
$ git checkout main
$ git checkout -b red

Voici à quoi cela ressemble en LEGO :

(Seth Kenlon CC BY-SA 4.0)

Vous pouvez désormais fournir uniquement du bleu au propriétaire du projet, ou simplement du rouge, ou les deux, et le propriétaire du projet peut décider quoi attacher à main. sur le dépôt officiel. Mieux encore, blue et red peuvent être développés séparément à l'avenir. Même si vous terminez blue et qu'il est fusionné dans main, une fois que le développeur de red fusionne les modifications de main alors ce qui était bleu devient disponible pour le nouveau développement rouge.

(Seth Kenlon CC BY-SA 4.0)

Exemple de branche

Voici une démonstration simple de ce principe. Tout d’abord, créez un dépôt Git avec une branche principale :

$ mkdir example
$ cd example
$ git init -b main

Remplissez votre projet naissant avec un exemple de fichier :

$ echo "Hello world" > example.txt
$ git add example.txt
$ git commit -m 'Initial commit'

Ensuite, extrayez une branche appelée blue et faites un commit idiot que vous ne voulez pas conserver :

$ git checkout -b blue
$ fortune > example.txt
$ git add example.txt
$ git commit -m 'Unwisely wrote over the contents of example.txt'

Jetez un œil au journal :

$ git log --oneline
ba9915d Unwisely wrote over the contents of example.txt
55d4811 Initial commit

Tout d'abord, supposons que vous êtes heureux de continuer à développer sur blue. Créez une branche appelée red :

$ git checkout -b red

Jetez un œil au journal :

$ git log --oneline
ba9915d Unwisely wrote over the contents of example.txt
55d4811 Initial commit

Votre nouvelle branche red, et tout ce que vous développez en red, contient le commit que vous avez effectué en blue. Si c'est ce que vous souhaitez, vous pouvez alors procéder au développement. Cependant, si vous avez l'intention de prendre un nouveau départ, vous devez plutôt créer red à partir de main.

Maintenant, vérifiez votre branche principale :

$ git checkout main

Jetez un œil au journal :

$ git log --oneline
55d4811 Initial commit

Ça a l'air bien jusqu'à présent. La branche blue est isolée de main, c'est donc une base propre à partir de laquelle bifurquer dans une direction différente. Il est temps de réinitialiser la démo. Parce que vous n'avez encore rien fait sur red, vous pouvez le supprimer en toute sécurité. Si cela se produisait dans la vraie vie et que vous aviez commencé à développer sur red, vous devrez alors sélectionner vos modifications du rouge vers une nouvelle branche.

Ceci n'est qu'une démo, vous pouvez donc supprimer red en toute sécurité :

$ git branch -D red

Créez maintenant une nouvelle branche appelée red. Cette version du rouge est conçue comme un nouveau départ, distinct du bleu.

$ git checkout -b red
$ git log --oneline
55d4811 Initial commit

Essayez de faire un nouveau commit :

$ echo "hello world" >> example.txt
$ git add example.txt
$ git commit -m 'A new direction'

Regardez le journal :

$ git checkout -b red
$ git log --oneline
de834ff A new direction
55d4811 Initial commit

Jetez un dernier coup d'œil au bleu :

$ git checkout blue
$ git log --oneline
ba9915d Unwisely wrote over the contents of example.txt
55d4811 Initial commit

La branche rouge a sa propre histoire.

Le bleu a sa propre histoire.

Deux branches distinctes, toutes deux basées sur main.

Fourchette avec précaution

Comme beaucoup d'utilisateurs de Git, je trouve plus facile de suivre ma branche actuelle en utilisant une invite compatible Git. Après avoir lu l'article de Moshe Zadka à ce sujet, j'utilise Starship.rs et je l'ai trouvé très utile, en particulier lors de nombreuses mises à jour d'un projet d'empaquetage qui nécessite que toutes les demandes de fusion contiennent un seul commit sur exactement un. bifurquer.

Avec des centaines de mises à jour effectuées sur 20 participants ou plus, la seule façon de gérer cela est de vérifier souvent, d'extraire et de créer une nouvelle branche. Starship me rappelle instantanément ma branche actuelle et l'état de cette branche.

Que vous dériviez d'une nouvelle branche à partir de la branche principale ou à partir d'une autre branche dépend de ce que vous essayez d'accomplir. L’important est que vous compreniez que l’endroit où vous créez une succursale est important. Faites attention à votre branche actuelle.

Articles connexes: