notes_cm_td_m2_sesi/NMV/CM/NMV.tex

272 lines
11 KiB
TeX
Raw Permalink Normal View History

2023-10-06 12:52:58 +02:00
\input{packages.tex}
\newcounter{mypara}
\setcounter{mypara}{0}
\setcounter{secnumdepth}{4}
%Bibliography
\addbibresource{bibliographie.bib}
% Document
\begin{document}{
\sloppy
\input{titlepage.tex}
\setcounter{tocdepth}{4}
\setcounter{secnumdepth}{4}
% Table of contents
\tableofcontents
\newpage
\chapter*{Organisation}
Pas de projet, pas de partiel: la notation se fait avec un examen final (50\%) et un exposé (50\%), dont la soutenance aura lieu dix jours après l'examen.
\chapter{Fonctionnement interne de git}
\section{Introduction}
Pourquoi git ? C'est l'outil N°1 pour la gestion de version et de projet décentralisé. Ce logiciel permet d'avoir un historique sur les fichiers, de maintenir des branches alternatives. Le fait qu'il soit décentralisé, contrairement à SVN et CVS, implique une gestion de la cohérence sur l'historique. \newline
\newline
L'intérêt de ce cours est d'étudier le fonctionnement interne de git.
\section{Principes de base}
Tous les mécanismes de git reposent sur les diff/patchs et
\subsection{Patchs et diffs}
Un diff est une comparaison ligne à ligne de fichiers. Le patch est l'utilisation d'un diff pour faire évoluer un fichier et passer à une nouvelle version.
\subsection{Notion d'historique}
\subsubsection{Définition : historique}
On appelle historique un graphe orienté acyclique composé de version re-calculables à partir des versions adjacentes. \newline
\newline
Rappel : un arbre est un graphe connexe acyclique non orienté. L'historique n'est pas un arbre car il est orienté.
\subsubsection{Définition : branche}
On appelle branche de version $v_{i}$ d'un historique le sous-graphe composé de l'ensemble des noeuds adjacents.
\subsubsection{Définition : tronc}
Le tronc ou branche principale est définie selon le contexte.
\subsubsection{\#BalanceTonDépôt}
Depuis le 1er octobre 2020, la branche principale des dépôts créés sur les plateforme est nommée main au lieu de master. \newline
\newline
Le logiciel git émet un avertissement lors du git init.
\subsubsection{Définition : sous-branche}
Toute branche d'un noeud non incluse dans une autre branche est nommée sous-branche.
\subsubsection{Définition : merge}
Tout noeud du graphe ayant un degré sortant strictement supérieur à 1 est un merge (ou noeud de fusion).
\section{Historique}
\begin{itemize}
\item 2001 : Linux est développé sur CVS
\item 2002 - 2005 : Linux est développé sur Bitkeeper
\item 6 avril 2005 : Bitkeeper quitte le libre et Torvalds commence git
\item 18 avril 2005 : git sait merge
\item 16 juin 2005 : Linux développé officiellement sur git
\item 14 février 2007 : Sortie de la version 1.5.0
\end{itemize}
\section{Architecture interne}
À l'origine, git était destiné à constituer un système de fichiers !
\subsection{Création d'un dépôt}
À la création d'un dépôt, un répertoire .git est créé. \newline
\newline
Sur un serveur, une autre méthode est possible : il n'y a besoin que de l'historique (et pas des fichiers eux-mêmes). L'option faite pour cela est \texttt{--bare}
\subsection{Les objets : tout est blob}
Le système de git est conçu comme un système de fichiers versionnés. Linus Torvalds reprend les concepts de Linux :
\begin{itemize}
\item tout est fichier -> tout est blob ;
\item fichiers identifiés par numéro d'inode -> blobs identifiés par SHA-1 de leur contenu. \newline
\end{itemize}
L'identification par \textit{hash} n'est possible que si le contenu est fixe : un blob est immuable, entraînant une réduction de la taille des dépôts par déduplication !
\subsubsection{SHA-1}
C'est une fonction cryptographique conçue par la NSA, limitée à des fichiers de 2 exaoctets, retournant un \textit{hash} sur 160 bits noté avec 2 + 38 caractères hexadécimaux. \newline
\newline
Note : bien que largement vulnérable aux collisions, SHA-1 ne pose pas de problèmes pour les fichiers de texte a priori (probabilité de $\frac{1}{2^{160}}$ ). \newline
\newline
Note : pour vérifier l'intégrité, la commande \texttt{git fsck} est utile ! \newline
\newline
\subsection{Types d'objets}
\subsubsection{Blob}
C'est l'élement de base du stockage. Il est identifié par le SHA-1, stocké dans le dépôt sous \texttt{.git/objects/XX/YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY} sous la forme \texttt{"blob <taille de contenu>\textbackslash 0<contenu>"} \newline
\newline
Les blobs sont compressés avec la zlib. Le SHA-1 est calculé sur le blob et non sur le contenu !
\subsubsection{Trees}
Ce sont des blobs. Ils stockent la liste des pointeurs vers des blobs et d'autres trees en associant un nom à chaque pointeur. Un ensemble de trees permet de décrire l'état d'une hiérarchie de blobs. \newline
\newline
\subsubsection{Commits}
Un commit est l'enregistrement d'une nouvelle version de fichiers. Auparavant, dans CVS par exemple, on utilise la numération des patchs fichier par fichier (deltas, on a donc pas d'état global et ça oblige à ajouter des tags pour retrouver un état cohérent, l'accès à une version spécifique nécessite de ré-appliquer les patchs). Dans SVN, chaque numéro correspond à un état global cohérent mais là aussi il faut ré-appliquer les patchs. \newline
\newline
La résolution de ce problème par git consiste à numéroter globalement tous les fichiers, puisque la déduplication rend l'opération atomique.
Ce sont des blobs. Ils un pointeur vers un tree dont on veut sauver l'état, un pointeur vers un ou plusieurs autre commits pour constituer un historique, et également le nom d'un auteur et d'un committeur, puis une description sous forme d'une chaîne de caractère. \newline
\newline
\textbf{ATTENTION :} les blobs de commit contiennent des références de date en notation Epoch, rendant le hash liée à la date de création du commit. Ainsi même avec les mêmes fichiers et les mêmes modifications, personne n'aura le même hash de commit sauf à l'effectuer exactement au même moment.
\subsubsection{Tags}
Ce sont des blobs. Ils contiennent un pointeur vers un blob, un tree ou un commit, ainsi qu'une signature.
\section{Architecture générale}
\subsection{Commandes}
Ce logiciel est conçu avec la philosophie Unix des commandes. Ainsi, chaque commande git a son propre binaire ! Il y a 145 commandes, dont 19 sont dédiées au dépôts locaux, 5 pour les dépôts distants, et quelques autres pour gérer les conflits et les recherches d'erreurs.
\subsection{Exemple simple}
Lors de la création d'un projet, on utilise \texttt{git init} pour créer l'enveloppe du dépôt. Ensuite on ajoute un ou des fichiers avec \texttt{git add} crée un ou des blobs liés à un tree. En utilisant \texttt{git commit} on obtient alors un commit. \newline
\newline
L'état courant est indiqué par \texttt{head} et l'index pointe vers le tree pointé par le commit pointé par \texttt{head}. \newline
\newline
On remarque facilement que la structure de git a inspiré la \textit{blockchain}.
\subsection{Branches et fusion}
Pour manipuler les branches on a :
\begin{itemize}
\item branch : liste les branches avec une * pour la branche active ;
\item branch <nom> : créé une nouvelle branche <nom> ;
\item branch -m : permet de renommer une branche ;
\item branch -d : permet de supprimer une branche ;
\item switch : permet de changer de branche active ;
\item switch -c : créé une branche et l'active ;
\item show-branch : affiche les branches et leur commits.
\end{itemize}
Créer une branche, c'est créer un pointeur vers un commit (comme un tag !). Si on réalise un commit sur une branche, on va créer un historique et la référence à la branche se déplacera. \newline
\newline
Note : une bonne pratique est de créer une branche à chaque séance de travail et la fusionner (\textit{fast-forward} !) en fin de session de travail. \newline
\newline
La fusion en \textit{fast-forward} est atomique (on déplace le pointeur de la branche). Par contre, si cela n'est pas possible parcequ'on a deux branches parallèles impliquées, il faut créer un nouveau commit dit \textit{commit de fusion}. Pourtant, les modifications dans ces deux branches sont probablement indépendantes ! La solution : \texttt{git rebase}. \newline
\newline
Le \textit{rebase} est une transposition d'un commit de sa base initiale à une nouvelle base. Lors de cette transposition, de nouveaux commits sont créés. Les précédents ne sont pas effacés, sauf après utilisation de \texttt{git gc} (après 7 jours parceque Torvalds sait que les programmeurs sont des boulets). \newline
\newline
\subsection{Les remords}
On a trois types de correction :
\begin{itemize}
\item revert : pour annuler un commit ;
\item amend : modifier le dernier commit ;
\item reset : rétablir la situation d'un ancien commit.
\end{itemize}
Le revert et le amend sont assez simples à comprendre. \newline
\newline
Pour reset, on a trois modes \texttt{--hard} (restaure les fichiers tels qu'ils étaient avant), normal (laisse les fichiers modifiés dans leur état, non suivis) et \texttt{--soft} (laisse les fichiers modifiés dans leur état dans l'index, prêts à commit).
\subsection{Utilisation de l'historique}
La commande \texttt{git diff} permet de travailler sur l'index lui-même. On peut notamment obtenir les différences entre le répertoire de travail et l'index, \texttt{head} et l'index etc. \newline
\newline
La commande \texttt{git show} donne le diff sous forme d'un patch (pour un commit).
\section{Décentralisation}
\subsection{Dépôts centralisés vs décentralisés}
Contrairement à SVN ou CVS, git est décentralisé. Cela signifie qu'il y a deux actions pour pousser une modification et également deux actions pour récupérer les modifications. De façon intéressante, \texttt{git pull} est la fusion entre \texttt{git fetch} et \texttt{git merge}. En tout cas, git permet de versionner localement et sans connexion internet avec un accès complet au passé.
\subsection{Gestion des conflits}
Le logiciel git permet de gérer les conflits localement lors des fusions, contrairement à SVN ou CVS qui rencontraient les conflits dès la récupération des modifications.
\subsection{Vue de la branche distance}
Sur un dépôt local, lors d'un clonage, le dépôt local contient une branche locale ainsi que la vue de la branche distante (généralement préfixée par \textit{origin}).
%% First chapter
%\chapter{Introduction}
%
%Blablabla
%
%\begin{figure}[h!]
% \center
% \includegraphics{images/su.png}
% \caption{Petite image}
% \label{fig:schema1}
%\end{figure}
%
%\setstretch{1}
%\section{Une section}
%\setstretch{1.3}
%
%Blabla \newline
%Blablabla.
%
%\setstretch{1}
%\subsection{Une sous-section}
%\setstretch{1.3}
%
%Bla à propos de l'\textbf{bla important} dont le fonctionnement est schématisé dans la figure \ref{fig:schema1}.
%
%% Second chapter
%\chapter{Seconde chose à dire}
%
%A ce propos \textit{italique}.
%
%\begin{figure}[h!]
% \center
% \includegraphics[width=\linewidth]{images/su.png}
% \caption{Image pleine page}
% \label{fig:image_pleine}
%\end{figure}
%
%\setstretch{1}
%\section{Une section}
%\setstretch{1.3}
%
%Texte pour dire tout ça parceque oui. \newline
%
%Ceci ne veut pas dire cependant que :
%
%\begin{itemize}
%\item Élément 1
%
%\item Élément 2
%
%\item Élément 3
%
%\end{itemize}
\newpage
% Bibliography
\nocite{*}
\addcontentsline{toc}{chapter}{Bibliographie}
\printbibliography
\end{document}