11 votes

Avantages et inconvénients des différents modèles de ramification dans les DVCS

Les trois grands du contrôle de version distribué (Git, Bazaar et Mercurial) traitent chacun les ramifications de manière assez différente. Dans Bazaar, par exemple, les branches sont des dépôts séparés (en fait, des copies divergentes du dépôt parent) ; sur votre système de fichiers, les différentes branches vivent dans des répertoires différents. Dans Git, en revanche, vous pouvez avoir plusieurs branches existant dans le même dépôt (et donc dans le même répertoire sur votre système de fichiers). Mercurial supporte les deux comportements ce dernier avec branches nommées .

Quels sont les avantages et les inconvénients de ces différents modèles de ramification ? À mon avis, l'approche de Bazaar (une branche, un repo) rend le branchement plus pénible que l'approche de Git (par exemple, pour utiliser une branche dans Bazaar, je dois d'abord créer la branche, puis cd out de ma copie de travail actuelle, puis check out de la nouvelle branche, comme je le ferais dans SVN).

10voto

Lukáš Lalinský Points 22537

Bazaar n'exige pas que vous travailliez de la manière que vous décrivez. J'ai en fait écrit un article de blog à ce sujet il y a deux jours. Vous pouvez travailler pratiquement avec un seul arbre de travail, en passant d'une branche à l'autre et en créant de nouvelles branches sans quitter l'arbre de travail. Les commandes utiles pour cela sont : checkout , switch , branch --switch . Consultez le site flux de travail de Bazaar, vous verrez qu'il est possible de le configurer comme vous le souhaitez.

6voto

Jakub Narębski Points 87537

Je ne connais pas bien les modèles de branchement dans les VCS autres que Git. Je dirais que dans n'importe quel VCS, vous pouvez implémenter le branchement par clonage (vous créez une branche en faisant un clone). Les "branches nommées" de Mercurial sont (d'après ce que j'ai compris) en fait étiquettes d'engagement n'est interprété que comme une branche, ce qui nécessite parfois une numérotation locale des révisions pour résoudre l'ambiguïté. Les "signets" Mercurial sont, je pense, assez similaires aux branches Git. Les deux DVCS qui ont très Les différents concepts de ramification sont Monotone y Darcs . Je pense que le "branching by copying" utilisé par Subversion, où la séparation entre le nom du projet et le nom de la branche se fait par convention est une mauvaise idée.


Dans Git, les révisions forment un graphe acyclique dirigé (DAG) de commits. Ce graphe est orienté, car les modifications ont des parents. C'est un point très important : les arêtes du DAG des commits vont du commit à son parent (ou, dans le cas d'un commit de fusion, à deux ou plusieurs de ses parents). Le graphe des livraisons est acyclique, ce qui signifie qu'il n'existe aucune chaîne (aucun chemin) qui commence et se termine par le même objet.

Glossaire Git définit la "branche" comme un ligne active de développement . Cette idée est à l'origine d'une implémentation des branches dans Git.

Le commit le plus récent sur une branche est appelé le pointe de cette branche. L'extrémité de la branche est référencée par un chef de branche qui n'est qu'un nom symbolique pour ce commit. Dans sa forme "libre", une telle tête de branche (par exemple pour une branche nommée "master") est juste un fichier quelque part dans le répertoire refs/heads/ à l'intérieur du dépôt git (à l'intérieur de .git dir), qui contient une référence à l'extrémité actuelle d'une branche : son identifiant SHA-1 du commit (sous forme de chaîne hexadécimale).

Lorsque vous créez un nouveau commit dans Git, l'extrémité de la branche actuellement vérifiée avance. En d'autres termes, le nouveau commit est créé sur la pointe de la branche actuelle, et la tête de la branche avance jusqu'au nouveau commit (un peu comme le pointeur au sommet de la pile pourrait avancer).

Un dépôt git unique peut suivre un nombre arbitraire de branches, mais votre arbre de travail (si vous en avez un) est associé à une seule d'entre elles (la branche "courante" ou "vérifiée"). La branche courante est donnée par le pointeur HEAD. HEAD est (généralement) un pointeur vers la branche actuellement extraite (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 la branche actuellement extraite est "master", alors .git/HEAD (représentant HEAD) contiendrait une seule ligne terminée par LF avec ref: refs/heads/master (référence symbolique à refs/heads/master ), et .git/refs/heads/master (tête de la branche "master") contiendrait par exemple la ligne terminée par LF 0b127cb8ab975e43398a2b449563ccb78c437255 qui est l'identifiant SHA-1 de l'extrémité de la branche 'master' (c'est-à-dire si la branche actuelle n'est pas 'packed' : il faut alors jeter un coup d'œil à .git/packed-refs ).

Certaines commandes de Git, telles que "git commit" ou "git reset" manipulent / modifient la tête de branche ; d'autres, telles que "git checkout" manipulent / modifient HEAD (référence symbolique à la branche courante).

" git log _branch_ La commande " montre tous les commit accessibles depuis l'extrémité de la branche, c'est-à-dire l'extrémité de la branche, son parent, le (ou les) parent(s) de ce commit parent, etc. Elle montre une partie d'un DAG de commits.

Dans Git, supprimer une branche signifie simplement supprimer une tête de branche. Cela peut signifier que certains commits deviennent "invisibles", inaccessibles depuis les refs (branches et tags), ce qui signifie qu'à un moment donné ces commits pourraient être ramassés et supprimés du dépôt. Mais si vous pouvez supprimer une branche avec "git branch -d <branchname>" alors cela signifie qu'aucun commit ne sera perdu ; vous pouvez forcer la suppression de la branche avec "git branch -D <branchname>". Renommer une branche consiste simplement à renommer branch head, une référence symbolique (nom symbolique) de branch tip ; les noms de branches ne sont sauvegardés nulle part dans l'objet commit.


Git a également le concept de reflogs qui est un historique local de l'endroit où la pointe de la branche a pointé (et à quel moment). Par exemple, si vous modifiez un commit avec "git commit --amend", la pointe de branche sera remplacée par le commit modifié, et HEAD^ sera le parent du commit avant et après la modification, tandis qu'il y aura une entrée dans reflog pour la version avant la modification et après la modification. Si vous remontez l'historique en utilisant "git reset", reflog contiendra les informations de l'ancienne branche avant le retour en arrière.

En résumé, reflog offre une sécurité supplémentaire et une récupération facile des commandes git.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X