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.