2009-10-31 5 views
11

Les trois grands du contrôle de version distribuée (Git, Bazaar et Mercurial) traitent chacun différemment les dérivations. Dans Bazaar, par exemple, les branches sont des mises séparées (en fait, des copies divergentes du repo parent); sur votre système de fichiers, différentes branches vivent dans des répertoires différents. Dans Git, en revanche, vous pouvez avoir plusieurs branches dans le même référentiel (et donc dans le même répertoire sur votre système de fichiers). Mercurial prend en charge both behaviors, ce dernier avec named branches.Avantages et inconvénients des différents modèles de branchement dans DVCS

Quels sont les avantages et les inconvénients associés à ces différents modèles de branchement? Dans mon esprit, l'approche de Bazaar d'une branche, un repo rend la branche plus d'une douleur que l'approche de Git (par exemple pour utiliser une branche dans Bazaar, je dois d'abord créer la branche, puis cd sur ma copie de travail actuelle, puis la nouvelle branche, comme je le ferais en SVN).

+4

branches nommées est assez différente de branches git, voir ici pour plus de détails: http://stevelosh.com/blog/entry/2009/8/30/a-guide-to-branching-in-mercurial/ – tonfa

+0

Voir aussi Ma réponse dans "Git et Mercurial - Compare and Contrast", qui couvre aussi les branches: http://stackoverflow.com/questions/1598759/git-and-mercurial-compare-and-contrast/1599930#1599930 –

+0

L'homme, tonfa toujours parvient à poster mon blog avant moi! :) –

Répondre

9

Bazaar ne vous oblige pas à travailler comme vous le décrivez. J'ai effectivement écrit a blog post à ce sujet il y a deux jours. Vous pouvez travailler à peu près avec un seul arbre de travail, basculer entre différentes branches et créer de nouvelles branches sans quitter l'arbre de travail. Des commandes utiles pour cela sont: checkout, switch, branch --switch. Consultez la documentation workflow pour Bazaar, vous verrez que vous pouvez le configurer de la manière que vous voulez.

+0

Il est bon de savoir que Bazaar est plus flexible que je ne le pensais. Je me demandais vraiment si la création d'un répertoire "branches" à l'intérieur de votre repo pourrait résoudre le problème que j'ai mentionné dans ma question. Merci pour la perspicacité. – ThisSuitIsBlackNot

6

Je ne connais pas beaucoup de modèles de branchement dans VCS autre que Git. Je dirais que dans n'importe quel DVCS, vous pouvez implémenter une branche en clonant (vous créez une branche en faisant un clone). Mercurial soi-disant "branches nommées" sont (d'après ce que je comprends) en fait commettre des étiquettes seulement interprété comme une branche, nécessitant parfois une numérotation locale des révisions pour résoudre l'ambiguïté. Mercurial "marque-pages" ar, je pense, tout à fait similaire aux branches Git. Les deux DVCS qui ont très concept différent de ramification sont Monotone et Darcs. Je pense que "ramifier en copiant" que Subversion utilise, où la séparation entre le nom du projet et le nom de la branche est convention, est une idée fausse.


Dans les révisions Git forment un graphique acyclique dirigé (DAG) de commits. C'est dirigé, parce que les commits ont des parents. C'est un problème très important: les bords dans le DAG des commits sont de commit à son parent (ou, dans le cas de commit de fusion, deux ou plus de ses parents). Le graphe des commits est acyclique, ce qui signifie qu'il n'y a pas de chaîne (pas de chemin) qui commence et finit avec le même objet.

Git glossary définit «branche» comme ligne de développement active. Cette idée est derrière une implémentation de branches dans Git.

La validation la plus récente sur une branche est appelée astuce de cette branche. La pointe de la branche est référencée par une tête de branche , qui est juste un nom symbolique pour cette validation. Dans sa forme "loose" une telle branche (par exemple pour la branche 'master') est juste un fichier quelque part dans le répertoire refs/heads/ dans le dépôt git (dans le répertoire .git dir), qui contient la référence à la pointe actuelle d'une branche: son SHA-1 identifiant de commit (en tant que chaîne hexadécimale).

Lorsque vous créez un nouveau commit dans Git, l'extrémité de la branche actuellement extraite avance. En d'autres termes, la nouvelle validation est créée au sommet de la branche courante, et la tête de la branche avance vers la nouvelle validation (un peu comme le pointeur vers le haut de la pile peut avancer).Un référentiel git unique peut suivre un nombre arbitraire de branches, mais votre arbre de travail (si vous en avez) est associé à un seul d'entre eux (la branche "current" ou "checked out"). La branche actuelle est donnée par le pointeur HEAD. HEAD est (généralement) un pointeur vers la branche actuellement retirée (vers un nom de tête de branche), tout comme les têtes de branches sont des pointeurs vers les extrémités des branches.

Par exemple, si actuellement emprunté branche est « maître », alors le fichier .git/HEAD (représentant HEAD) contiendrait la ligne à terminaison unique LF avec ref: refs/heads/master (une référence symbolique à refs/heads/master), et .git/refs/heads/master (tête de branche « maître ») serait contient par exemple la ligne LF terminée 0b127cb8ab975e43398a2b449563ccb78c437255, qui est l'identificateur SHA-1 à l'extrémité de la branche 'master' (c'est-à-dire si la branche courante n'est pas 'packed': alors vous devez jeter un oeil à .git/packed-refs).

Certaines commandes de Git, telles que "git commit" ou "git reset" manipulent/changent la tête de branche; d'autres tels que "git checkout" manipulent/changent HEAD (référence symbolique à la branche actuelle). La commande "git log branch" affiche tous les commit accessibles depuis l'extrémité de la branche, ce qui signifie l'extrémité de la branche, son parent, le parent (ou les parents) de ce parent, etc. Il montre une partie d'un DAG de commits.

Dans Git, la suppression d'une branche signifie simplement la suppression d'une tête de branche. Cela peut signifier que certains commits deviennent des références freins (branches et tags) "invisibles", inaccessibles, ce qui signifie qu'à un certain moment, ces commits pourraient récupérer les ordures et les retirer du dépôt. Mais si vous pouvez supprimer une branche avec "git branch -d <branchname>", cela signifie qu'aucun commit ne sera perdu; vous pouvez forcer la suppression de branche avec "git branch -D <branchname>". Renommer une branche consiste simplement à renommer la tête de branche, une référence symbolique (nom symbolique) de l'extrémité de la branche; les noms de branche ne sont pas enregistrés dans l'objet commit.


Git a aussi concept de reflogs, ce qui est une histoire locale de l'endroit où la pointe de la branche a (et quand). Par exemple, si vous modifiez un commit avec "git commit --amend", l'astuce de branche sera remplacée par commit modifié, et HEAD^sera parent de commit avant et après amending, alors qu'il y aurait une entrée dans reflog pour la version avant modification et après modification. Si vous rembobinez l'historique en utilisant "git reset", reflog contiendra des informations sur l'ancienne extrémité de la branche avant le rembobinage.

En bref, le reflet offre une sécurité supplémentaire et une restauration facile aux commandes git.

Questions connexes