Que signifie «ramification libre» dans Git?

27

Qu'est-ce que "ramification est libre" signifie dans Git?

J'entends beaucoup cela chaque fois que Git est mentionné par rapport à d'autres systèmes de contrôle de version.

Je n'ai pas eu l'occasion (?) De traiter avec d'autres ( SVN , etc.), alors comment la branche est-elle "chère" chez les autres?

laggingreflex
la source

Réponses:

28

L'affirmation selon laquelle "la ramification est gratuite dans git" est une simplification des faits car elle n'est pas "gratuite" en soi. En regardant sous le capot, une affirmation plus correcte serait de dire que le branchement est plutôt bon marché , car les branches sont essentiellement des références aux commits . Je définis ici le «bon marché» comme le moins de frais généraux le moins cher.

Permet de comprendre pourquoi Git est si «bon marché» en examinant les types de frais généraux dont il dispose:

Comment les branches sont-elles implémentées dans git?

Le référentiel git, .gitse compose principalement de répertoires avec des fichiers qui contiennent des métadonnées que git utilise. Chaque fois que vous créez une branche dans git, avec par exemple git branch {name_of_branch}, quelques choses se produisent:

  • Une référence est créée à la succursale locale à: .git/refs/heads/{name_of_branch}
  • Un journal d'historique est créé pour la succursale locale à: .git/logs/refs/heads/{name_of_branch}

C'est fondamentalement ça, quelques fichiers texte sont créés. Si vous ouvrez la référence en tant que fichier texte, le contenu sera l'id-sha du commit sur lequel la branche pointe. Notez que la ramification ne vous oblige pas à effectuer de validation car il s'agit d'un autre type d'objet. Les branches et les commits sont des «citoyens de première classe» dans git et une façon est de considérer la relation branche-à-commettre comme une agrégation plutôt qu'une composition. Si vous supprimez une branche, les validations continueront d'exister en tant que "balançant". Si vous avez accidentellement supprimé une branche, vous pouvez toujours essayer de trouver le commit avec git-lost-foundou git-fsck --lost-foundet créer une branche sur le sha-id que vous trouvez suspendu (et tant que git n'a pas encore fait de ramasse-miettes).

Alors, comment git garde-t-il la branche sur laquelle vous travaillez? La réponse est avec le .git/HEADfichier, qui ressemble un peu à ceci si vous êtes sur la masterbranche.

ref: refs/heads/master

Le changement de branche modifie simplement la référence dans le .git/HEADfichier, puis modifie le contenu de votre espace de travail avec ceux définis dans la validation.

Comment cela se compare-t-il dans d'autres systèmes de contrôle de version?

Dans Subversion , les branches sont des répertoires virtuels dans le référentiel . Donc, la façon la plus simple de créer une branche est de le faire à distance, avec un seul revêtement svn copy {trunk-url} {branch-url} -m "Branched it!". Ce que SVN fera est le suivant:

  • Copiez le répertoire source, par exemple trunk, dans un répertoire cible,
  • Validez les modifications pour finaliser l'action de copie.

Vous souhaiterez effectuer cette action à distance sur le serveur, car effectuer cette copie localement est une opération linéaire, les fichiers étant copiés et liés. C'est une opération très lente , alors que le faire sur le serveur est une opération à temps constant. Notez que même lors de l'exécution de la branche sur le serveur, subversion nécessite un commit lors de la branche alors que git ne le fait pas, ce qui est une différence clé. C'est un type de surcharge qui rend le SVN légèrement moins cher que Git.

La commande pour changer de branche dans SVN , c'est svn switch-à- dire , est vraiment svn updatedéguisée. Grâce au concept de répertoire virtuel, la commande est un peu plus flexible dans svn que dans git. Les sous-répertoires de votre espace de travail peuvent être désactivés pour refléter une autre URL de référentiel. La chose la plus proche serait d'utiliser, git-submodulemais son utilisation est sémantiquement très différente de la ramification. Malheureusement, c'est également une décision de conception qui rend la commutation un peu plus lente dans SVN que dans Git car il doit vérifier tous les répertoires de l'espace de travail dont l'URL à distance est en miroir. D'après mon expérience, Git est plus rapide pour changer de branche que SVN.

La branche de SVN a un coût car elle copie des fichiers et doit toujours être rendue publique. En git, comme expliqué ci-dessus, les branches sont "juste des références" et peuvent être conservées dans votre référentiel local et être publiées à votre discrétion. D'après mon expérience, SVN est toujours remarquablement moins cher et plus performant que par exemple ClearCase.

Ce n'est qu'une déception que SVN ne soit pas décentralisé. Vous pouvez avoir plusieurs référentiels en miroir sur un référentiel source, mais la synchronisation des modifications différentes de plusieurs référentiels SVN n'est pas possible car SVN n'a pas d'identificateurs uniques pour les validations (git a des identificateurs hachés qui sont basés sur le contenu de la validation). La raison pour laquelle j'ai personnellement commencé à utiliser git sur SVN est que le lancement d'un référentiel est remarquablement plus facile et moins cher dans git . Conceptuellement, en termes de gestion de la configuration logicielle, chaque copie divergente d'un projet (clone, fork, espace de travail ou autre) est une "branche", et étant donné cette terminologie, la création d'une nouvelle copie dans SVN n'est pas aussi bon marché que Git, où ce dernier a branches "intégrées".

Comme autre exemple, dans Mercurial , la création de branches a commencé un peu différemment en tant que DVCS et la création / destruction de branches nommées nécessitait des validations séparées. Les développeurs Mercurial sont implémentés plus tard dans les signets de développement pour imiter le même modèle de branchement de git, mais headssont appelés tipset branchessont bookmarksplutôt dans la terminologie mercurial.

Spoike
la source
Sensationnel. Merci beaucoup pour l'explication "chère".
laggingreflex
2
À partir de votre propre source: This command causes a near-instantaneous commit in the repository, creating a new directory in revision 341. The new directory is a copy of /calc/trunk.- La création de la branche est triviale dans SVN, à moins que vous ne fassiez explicitement une copie de chaque fichier.
Bobson
@Bobson Je pensais à réécrire les bits de branchement, car je fais beaucoup de handwaving à ce sujet, mais mon argument est toujours qu'un commit est nécessaire pour créer une branche alors que dans Git ce n'est pas le cas. Dans mon humble expérience, je pense toujours que le changement de branche dans SVN est plus lent que dans Git, mais je ne peux pas expliquer pourquoi.
Spoike
2
@Spoike - Changer, certainement. Et un commit est définitivement requis. J'ai fait un montage pour clarifier le bit avec lequel j'avais un problème. N'hésitez pas à le revenir si vous préférez.
Bobson
10

Dans Git, une branche est juste une référence à un commit sur le référentiel local. Le créer est très bon marché, pas de réseau du tout. Pas tout à fait gratuit (vous devez taper une commande), mais sacrément proche.

Le branchement n'est pas particulièrement cher dans SVN - c'est juste une copie, ce qui est un commit très bon marché. SVN a un modèle de référentiel central, c'est donc un accès réseau, mais pas horrible.

Dans le vénérable CVS, en revanche, la ramification est TRÈS chère. Fondamentalement, les branches CVS impliquent l'ajout d'une balise, mais dans CVS, cela signifie que CHAQUE FICHIER AFFECTÉ doit être modifié. Chaque fichier est réécrit pour inclure la nouvelle balise. C'est horriblement cher. Et si votre référentiel est grand, il est également horriblement lent. En fait, si vous êtes sur un gros projet, c'est assez lent pour que certaines personnes aient tendance à éviter de créer des succursales si elles le peuvent.

Michael Kohne
la source
4
Avec Git, c'est encore moins qu'une validation - une branche n'est qu'une étiquette. Et SVN semble aussi cher que CVS, car ils copient tous les deux tous les fichiers.
Izkata
8
@Izkata: si nous voyons du point de vue de l'utilisateur - oui, tous les fichiers sont copiés, du point de vue de l'implémentation (et des performances) - non, juste un enregistrement sur la copie est ajouté.
maxim1000
@Izkata trop pour commenter - voir ma réponse.
gbjbaanb
6
@Izkata SVN crée des pointeurs et des références, il ne copie pas tout.
Aaron McIver
2
Une branche Git n'est pas une validation, c'est juste une référence à une validation qui peut être déplacée librement vers d'autres validations. Considérez un dépôt Git comme un simple arbre de commits et des branches comme des notes autocollantes qui peuvent être librement déplacées vers différents commits sur cet arbre.
40XUserNotFound
5

Le branchement de SVN est aussi gratuit que celui de Git. C'est juste un peu de données internes qui indiquent où commence la succursale, aucune modification des fichiers stockés. Une «copie» dans SVN, c'est comme ajouter un lien symbolique vers un répertoire Unix. Notez que la branche SVN ne nécessitera pas de déplacement réseau jusqu'à ce que vous validiez vos modifications de copie de travail (mais il n'y a pas grand-chose à avoir un SCM si vous ne vous engagez pas hors local à un moment donné).

Notez qu'une branche Git impliquera également un certain ménage - comme l'ajout de cette balise en interne - qui devra être stocké quelque part lorsque vous vous engagez. Ce n'est pas un gros problème du tout, c'est pourquoi il est appelé «gratuit».

gbjbaanb
la source
5

Il est `` gratuit '' (dans ce contexte, `` gratuit '' signifie vraiment rapide et facile et ne prend pas de place) car dans certains systèmes de contrôle de version plus anciens, une branche était une copie complète du code à ce moment-là, donc les branches prenaient beaucoup de l'espace et il était facile de se retrouver avec beaucoup de différentes versions complètement complètes du logiciel qui traînaient, qui ont ensuite pris la gestion. Dans d'autres, ce n'était pas une copie complète du code, mais chaque fichier devait encore être modifié pour une balise, ce qui était lent et douloureux («coûteux»).

Les branches de git sont essentiellement des étiquettes pointant sur un commit et évitent ainsi les problèmes ci-dessus.

Michael Durrant
la source
1

Un autre aspect de «gratuit / bon marché / cher» est de savoir combien coûtent les ressources du développeur pour faire face aux conséquences en aval de la ramification; c'est-à-dire le processus de fusion des changements des branches.

Et ici, la fusion de branches dans des systèmes DVCS comme Git et Mercurial est plus facile que dans des systèmes plus anciens ... parce que les systèmes DVCS font un bien meilleur travail de suivi de l'historique des versions dans le graphique; c'est-à-dire là où une ramification précédente a eu lieu. Cela rend les fusions plus précises, réduit les conflits inutiles et ... rend la fusion subjective "plus facile" ou "moins effrayante" pour les développeurs impliqués.

Stephen C
la source