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, .git
se 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-found
ou git-fsck --lost-found
et 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/HEAD
fichier, qui ressemble un peu à ceci si vous êtes sur la master
branche.
ref: refs/heads/master
Le changement de branche modifie simplement la référence dans le .git/HEAD
fichier, 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 update
dé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-submodule
mais 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 heads
sont appelés tips
et branches
sont bookmarks
plutôt dans la terminologie mercurial.
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.Le coût réel d'une succursale est de la fusionner. Git rend cela plus facile que certains autres systèmes de contrôle de source. Voir la question Stack Overflow Comment et / ou pourquoi la fusion dans Git est-elle meilleure que dans SVN? .
la source
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.
la source
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».
la source
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.
la source
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.
la source