GIT de l'intérieur: introduction (traduction)

Bonjour, Habr! Je vous présente la traduction de l'article "Git for Computer Scientists" de Tommi Virtanen.


GIT Inside Out: une introduction


De moi-même: j'ai lu périodiquement des articles sur la façon dont diverses technologies populaires sont organisées sous le capot, je suis tombé sur ce matériau . L'article semblait intéressant par la présence de schémas simples et compréhensibles, qui sont bien mieux perçus que les feuilles d'un texte terne. J'ai décidé de traduire en russe. Images prises de l'original.


Qui sera intéressé et peut-être utile: les personnes qui travaillent avec Git tous les jours (c'est-à-dire toutes les secondes, sinon le premier développeur de logiciels), et qui souhaitent mieux comprendre le mécanisme de son travail.


Remarque: pour une meilleure compréhension de l'article, il faut avoir une idée d'une telle bête comme un graphique acyclique dirigé (DAG) .


Stockage d'objets


Le référentiel d'objets Git est, en gros, un DAG contenant divers types d'objets. Les objets sont stockés sous forme compressée et identifiés par des hachages SHA-1 (ce n'est PAS un hachage du contenu du fichier qui représente l'objet, mais de sa présentation dans Git).


Blob


image


Blob est un objet simple, juste une collection d'octets. Il peut s'agir d'un fichier, d'un lien symbolique ou autre. La sémantique est déterminée par l'objet qui pointe vers ce blob.


Arbre


image


Les objets de type "arbre" décrivent des répertoires (répertoires). Ils peuvent pointer vers des objets blob qui stockent le contenu des fichiers, ainsi que vers d'autres arborescences, créant ainsi une structure de sous-répertoire.


Si un nœud pointe vers un autre nœud dans le DAG, ils disent que cela dépend de ce nœud, c'est-à-dire ne peut exister sans elle. Les nœuds pointés par un nœud peuvent être supprimés à l'aide de la récupération de place (commande git gc ), ou restaurés à l'aide de la commande git fsck --lost-found .


Valider


image


La validation fait référence à une arborescence représentant l'état des fichiers dans Git au moment de la création de la validation. En outre, commit peut faire référence à d'autres validations qui sont ses parents:


  • Si la validation a plus d'un parent, cela signifie qu'elle décrit l'opération de fusion (fusion)
  • Si la validation n'a pas de parents, il s'agit de la validation dite initiale (initiale) (c'est-à-dire la première du référentiel)
  • Il peut également y avoir des cas où il y a plus d'une validation initiale dans le référentiel - cela signifie généralement la fusion de deux référentiels distincts

Le corps de l'objet commit est un message commit .


Refs (liens)


image


Les liens (ou en-têtes ou branches) sont similaires à des autocollants avec des notes collées sur les nœuds DAG, une sorte de notes ou des signets - «Je travaille ici». Contrairement aux nœuds DAG, qui ne peuvent pas être modifiés et peuvent uniquement être ajoutés, les liens peuvent être déplacés à votre guise. Ils ne sont pas stockés dans l'historique et ne sont pas transférés directement entre les référentiels.


La commande git commit ajoute un nouveau nœud au DAG et y déplace un signet pour la branche actuelle.


Les liens se trouvent dans l' espace de noms heads / branchname , mais une partie des têtes peut être omise.


Le lien HEAD se distingue - il ne pointe pas vers un nœud, mais vers un autre lien - il s'agit d'un pointeur vers la branche active actuelle.


Références à distance


image


Ce sont, en gros, des autocollants d'une couleur différente. La différence est que les liens distants se trouvent dans un espace de noms différent et sont également gérés par un serveur distant. Pour les mettre à jour, utilisez la commande git fetch .


Tag



Une balise est une combinaison d'un nœud DAG et d'un autocollant (une autre couleur). Le tag pointe vers la validation et inclut un message facultatif et une signature GPG. Un autocollant (lien) est un moyen simple d'accéder au tag, et en cas de perte, il peut être restauré avec la commande git fsck --lost-found .


Ainsi, un référentiel Git est une combinaison de DAG et de liens.


L'histoire


Maintenant, sachant comment Git stocke l'historique des versions, essayons de décrire diverses opérations, ainsi que de comprendre comment Git diffère des systèmes représentant l'historique sous forme de changements linéaires pour chaque branche.


image


Le référentiel le plus simple. Nous venons de copier ( git clone ) le dépôt distant avec un seul commit.


image


Ici, nous lisons ( git fetch ) le dépôt distant et avons obtenu 1 nouveau commit, mais nous ne l'avons pas encore fusionné avec notre branche.


image


Voici ce qui se passe après l'exécution de la commande git merge remotes / MYSERVER / master . Comme la fusion a été effectuée en avance rapide (il n'y a pas eu de validation locale dans notre branche locale), les événements suivants se sont produits: les fichiers de notre copie de travail ont changé et le pointeur vers la branche a également été déplacé.


image


Exécutez git commit localement, puis git fetch . Nous avons maintenant un commit local et distant. De toute évidence, vous avez besoin d'une fusion .


image


C'est le résultat de la commande git merge remotes / MYSERVER / master . Étant donné que nous avions une validation locale, ce n'est pas une avance rapide et une validation distincte est créée pour la fusion dans le DAG. Remarque - il a 2 parents commit.


image


C'est ainsi que notre arborescence s'occupera de plusieurs commit-s, dans les deux branches (locale et distante) + fusion. Vous pouvez clairement voir comment Git DAG capture l'historique complet de nos actions.


image


Cependant, une telle histoire est difficile à lire. Si vous n'avez pas encore publié votre branche, ou si vous avez convenu avec d'autres membres de l'équipe qu'ils ne devraient pas en tirer parti dans leur travail, vous avez une alternative: vous pouvez rebaser votre branche. Dans ce cas, votre commit est remplacé par un autre commit, avec un parent différent, vers lequel le lien vers la branche se déplace également.


Dans ce cas, vos anciens commit resteront dans le DAG jusqu'à la récupération de place. En principe, il s'agit d'une sorte d'assurance, en cas de problème. Si vous avez toujours des liens vers un ancien commit, ils seront enregistrés tant que les liens existeront.


Vous ne devez PAS rebaser pour les branches au-dessus desquelles d'autres personnes ont créé un commit. Vous pouvez les restaurer (et même pas très difficiles), mais cela ajoute de la confusion et beaucoup de travail inutile.


image


Voici à quoi cela ressemble après le garbage collection (ou en ignorant les validations inaccessibles) et la création d'une nouvelle validation au-dessus de la branche à laquelle la rebase a été appliquée.


image


De plus, avec rebase, vous pouvez déplacer plusieurs validations en même temps.


C’est tout. J'espère que le matériel sera utile.

Source: https://habr.com/ru/post/fr468205/


All Articles