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.