\input{../_preamble}
\input{../_preamble_bbl}
% \usepackage{biblatex}
% \addbibresource{../bibliography}
\usepackage{menukeys}
\title{Git}
\usepackage{float}
\usepackage{dingbat}
\usepackage[newfloat]{minted}
\SetupFloatingEnvironment{listing}{listname=Listings}
\setminted{
  bgcolor=Lavender,
  breaklines,
  breaksymbolright=\small\carriagereturn}
\setmintedinline{bgcolor=Lavender}
\usepackage{capt-of}
\usepackage{soul}
\makeindex[name=cmds, intoc, title={Liste des commandes et
  instructions}, options={-s \jobname.ist}]

\NewDocumentCommand{\commande}{s m O{}}{
  \IfBooleanTF{#1}{\index[cmds]{#2@\texttt{#2}|#3textbf}}
  {\index[cmds]{#2@\texttt{#2}#3}}
}

\NewDocumentCommand{\inputfile}{O{} m m O{application/x-sh}}{
  \marginpar{\attachandlink{scripts/#3}[#4]{Fichier
      attaché}{\textcolor{blue}{Ouvrir le fichier}}}
  \inputminted[#1]{#2}{scripts/#3}
}

\usepackage{pdflscape}
\usepackage{adjustbox}

\begin{document}
\maketitle
\renewcommand{\contentsname}{Sommaire}
\tableofcontents

\listoffigures

% \listoflistings

% \needspace{3\baselineskip}
% \listoftables

\chapter{Introduction}
\label{cha:introduction}

\paragraph{Avertissement}
Dans les pages qui suivent, on cherche à donner au lecteur quelques
éléments sur la notion de \emph{système de contrôle de version} en
général et sur \emph{Git} en particulier. L'ouvrage de référence, par
\citeauthor{Chacon.Straub2018}, \citetitle{Chacon.Straub2018}, traduit
en français, est disponible en ligne\autocite{Chacon.Straub2018}.

\section{Les systèmes de contrôle de version}
\label{sec:vers-contr-syst}
Les \enquote{systèmes de contrôle de version}, en anglais
\emph{version control systems} (VCS), sont des logiciels qui
permettent de suivre toutes les modifications des fichiers et des
répertoires qui se trouvent dans un répertoire donné. À partir du
moment où l'on décide de suivre le contenu d'un répertoire, on peut
retrouver l'état qui était le sien dans le passé à tout moment.

Supposons que l'on ait quelque part modifié un paragraphe dans un
texte, ajouté ou retranché des lignes: le système de contrôle de
version permet alors de retrouver la chronologie de toutes les
modifications et de les afficher clairement, l'une après l'autre. On a
ainsi l'assurance de ne jamais rien perdre de son travail.

Le contrôle de version permet également de travailler en même temps
sur différentes \emph{branches}. On distingue ainsi la \emph{branche
  principale} de toutes les \emph{branches secondaires} que l'on peut
ouvrir à tout moment. Prenons un exemple: à un moment donné, on
souhaite revenir sur une page complexe que l'on a rédigée et y
apporter des modifications. Mais pour autant, on n'approuve pas encore
ces modifications et on voudrait ne rien perdre de la version
originale. On ouvre alors une \emph{branche secondaire} dans laquelle
on modifie à souhait la page. Durant tout le travail sur la branche
secondaire, le travail enregistré dans la branche principale n'est pas
altéré. Une fois terminé le travail sur la branche secondaire, on peut
l'abandonner ou bien, si le résultat est satisfaisant, le
conserver. Dans ce cas, on demande au système de contrôle de version
de \emph{fusionner} dans la branche principale la branche secondaire
sur laquelle on a travaillé. Puis on continue le travail dans la
branche principale, après avoir effacé la branche secondaire, tout en
sachant qu'à tout moment, toutes les étapes de ces modifications
peuvent être retrouvées. Bien entendu, le système permet d'ouvrir
simultanément autant de branches qu'on le souhaite.

\subsection{Différents concepts, différentes approches}
\label{sec:diff-conc-diff}
On distingue trois types de systèmes de contrôle de version:
\begin{enumerate}
\item \textbf{Les systèmes locaux} qui enregistrent les modifications
  dans une base de données. Quand un fichier est modifié, ces systèmes
  enregistrent non pas les deux versions du fichier modifié, mais un
  seul fichier, en plus du fichier initial, dans lequel sont
  simplement notées les \emph{différences} de l'un à l'autre.
\item \textbf{Les systèmes centralisés} qui font la même chose que les
  systèmes locaux, mais dans lesquels la base de données se trouve sur
  un serveur. L'avantage est que l'on peut alors organiser un travail
  de groupe. Mais l'inconvénient est que si le serveur est en panne,
  alors la base de données est inaccessible et personne ne peut
  travailler.
\item \textbf{Les systèmes distribués} dans lesquels les différents
  utilisateurs travaillent non pas sur des fichiers reconstitués à
  l'aide de la somme des modifications enregistrées sur un serveur,
  mais sur une version autonome et dupliquée de tous les fichiers qui
  sont sur le serveur. Chacun travaille sur ses fichiers, même hors
  réseau. Puis une fois le travail terminé, on envoie sur le serveur
  un nouvel état de la base de données que les autres peuvent
  synchroniser à tout moment.
\end{enumerate}

Git est un système de contrôle de version \emph{distribué}. Par
rapport à d'autres systèmes de la même catégorie, il offre un avantage
considérable: celui de travailler non pas sur les \emph{différences}
entre les modifications des fichiers, mais sur des \emph{instantanés}
complets. Prenons un exemple. Soit le fichier suivant
(\verb|recherche.txt|):\label{ref:recherche}
\begin{minted}[linenos]{text}
PREMIÈRE PARTIE
===============

COMBRAY
-------

I

Longtemps, je me suis couché très tôt. Parfois, à peine ma
bougie éteinte, mes yeux se fermaient si vite que j'avais juste le
temps de me dire: «Je m'endors.»
\end{minted}

Puis l'auteur se ravise et écrit:
\begin{minted}[linenos]{text}
PREMIÈRE PARTIE
===============

COMBRAY
-------

I

Longtemps, je me suis couché de bonne heure. Parfois, à peine ma
bougie éteinte, mes yeux se fermaient si vite que je n'avais pas le
temps de me dire: «Je m'endors.»
\end{minted}

Si l'on demande maintenant à un système informatique d'analyser les
différences entre les deux états de \verb|recherche.txt|, il pourra
produire un résultat comparable à celui-ci:

\label{ref:diff}
\begin{minted}[linenos,escapeinside=||]{text}
--- recherche.txt	2018-10-03 12:35:05.848903296 +0200
+++ recherche.txt	2018-10-03 12:31:04.292356175 +0200
|\textcolor{Blue}{@@ -6,6 +6,6 @@}|
 
 I
|\textcolor{Red}{-Longtemps, je me suis couché très tôt. Parfois, à peine ma}|
|\textcolor{Red}{-bougie éteinte, mes yeux se fermaient si vite que j'avais juste le}|
|\textcolor{Green}{+Longtemps, je me suis couché de bonne heure. Parfois, à peine ma}|
|\textcolor{Green}{+bougie éteinte, mes yeux se fermaient si vite que je n'avais pas le}|
 temps de me dire: «Je m'endors.»
\end{minted}

\paragraph{Commentaire}
La ligne~3 du rapport ci-dessus permet de comprendre que les
modifications n'interviennent pas avant la ligne~6 du fichier original
\verb|recherche.txt|. Ensuite, nous trouvons les modifications,
entourées de \emph{deux lignes non modifiées qui donnent le contexte}:
ce sont les lignes~5 et 10 du rapport, qui renvoient respectivement
aux lignes~7 et 11 du fichier original. Enfin, nous trouvons les
modifications: dans le rapport, les lignes~6 et 7, rendues en rouge et
précédées du signe $-$, ont été remplacées dans la deuxième version
par les lignes~8 et 9, rendues en vert, et précédées du signe $+$.

Les systèmes de contrôle de version peuvent donc procéder de deux
manières différentes:
\begin{enumerate}
\item Enregistrer le fichier original seulement, puis tous les
  rapports successifs qui donnent les modifications. Ainsi, pour
  donner l'état le plus récent d'un fichier, il suffit de prendre
  l'original puis de lui appliquer toutes les modifications
  successives.
\item Enregistrer toutes les versions successives des fichiers sous la
  forme d'\emph{instantanés}. Dans ce cas, les rapports qui
  enregistrent les modifications ne sont pas eux-mêmes enregistrés,
  mais peuvent toujours être produits à partir de deux instantanés
  enregistrés. \textbf{C'est ainsi que procède Git}.
\end{enumerate}

Bien entendu, quand on travaille sur de nombreux fichiers
simultanément et que, d'une étape à l'autre de son travail, on n'en
modifie que quelques-uns, Git ne prend pas d'instantané des fichiers
non modifiés. Au lieu de faire cela, il enregistre simplement un
\emph{pointeur} vers le dernier instantané du fichier, c'est-à-dire
vers la dernière version modifiée de ce fichier.

Cette méthode présente de nombreux avantages dont le plus évident
tient à la sécurité. En effet, les systèmes qui enregistrent seulement
les rapports de modifications ne sont plus en mesure de restituer un
fichier donné si l'un de ces rapports est corrompu. Si un chaînon est
manquant, c'est toute la chaîne qui est brisée. Git n'est pas
vulnérable sur ce point.

\section{Prise en main de Git}
\label{sec:prise-en-main}
\href{https://notabug.org/ralessi/courses/wiki#installation-de-git}{Une
fois Git installé}, il faut l'initialiser en lui indiquant votre nom
et votre email. Pour cela, il suffit d'entrer successivement les deux
lignes suivantes, en veillant à substituer à la fin de chaque ligne
les informations de l'exemple par celles de votre identité. On
veillera également à placer le prénom et le nom, séparé par un espace,
entre guillemets doubles:
\begin{minted}[linenos]{text}
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
\end{minted}

Ensuite, \href{./01-ligne-de-commande.pdf}{muni du cours sur la ligne
  de commande}, il est possible de créer un répertoire de
travail. Nous allons créer ce répertoire à l'intérieur de notre
répertoire \verb|Documents|, puis nous rendre à l'intérieur de ce
répertoire à l'aide de la commande \verb|cd|:
\begin{minted}{text}
[robert@kiddo ~]$ cd Documents
[robert@kiddo Documents]$ mkdir travail
[robert@kiddo Documents]$ cd travail
[robert@kiddo travail]$ 
\end{minted}

L'étape suivante consiste à demander à Git de suivre le contenu de ce
répertoire:
\begin{minted}{text}
[robert@kiddo travail]$ git init
Dépôt Git vide initialisé dans /home/robert/Documents/travail/.git/
\end{minted}

La réponse donnée par Git nous indique où sera maintenue sa base de
données: dans un
\href{./01-ligne-de-commande.pdf#lnk_hidden}{répertoire caché}
\verb|.git| à l'intérieur du répertoire \verb|travail|.

Commençons donc le travail. À l'aide d'un éditeur de texte, saisissons
le fichier \mintinline{text}|recherche.txt| donné
\vpageref{ref:recherche} et enregistrons-le dans sa première version.
La commande suivante \verb|git status| demande à Git de nous
\emph{fournir un état} du répertoire:
\begin{minted}[linenos,escapeinside=||]{text}
[robert@kiddo travail]$ git status 
Sur la branche master

Validation initiale

Fichiers non suivis:
  (utilisez "git add <fichier>..." pour inclure dans ce qui sera validé)

	|\textcolor{Red}{recherche.txt}|

aucune modification ajoutée à la validation mais des fichiers non suivis sont présents (utilisez "git add" pour les suivre)
\end{minted}

\paragraph{Commentaire}
Comme on le voit, Git est toujours très explicite. Voici ce qu'il faut
retenir ici de ce rapport:
\begin{enumerate}
\item Ligne~2: par défaut, la \emph{branche principale} est appelée
  par Git \verb|master|.
\item Ligne~6 et suivantes: Git donne une simple liste de fichiers
  trouvés dans le répertoire et indique qu'on ne lui a pas (encore)
  demandé de les \emph{suivre}. C'est un point important qu'il faut
  bien comprendre: \emph{Git ne suivra que les fichiers qu'on lui a
    demandé d'indexer}.
\item Ligne~7: Git nous donne la commande à utiliser pour indexer le
  fichier qui a été trouvé: \mintinline{bash}|git add <fichier>|
\end{enumerate}

Exécutons cette commande, puis demandons à Git un nouveau rapport:
\begin{minted}[linenos,escapeinside=||]{text}
[robert@kiddo travail]$ git add recherche.txt 
[robert@kiddo travail]$ git status 
Sur la branche master

Validation initiale

Modifications qui seront validées :
  (utilisez "git rm --cached <fichier>..." pour désindexer)

	|\textcolor{Green}{nouveau fichier : recherche.txt}|
\end{minted}

La commande \mintinline{bash}|git add recherche.txt| a eu pour effet
de placer \verb|recherche.txt| \emph{dans la zone d'index de Git} que
l'on appelle \emph{zone de travail} ou \emph{staging area}.

La dernière opération consiste à enregistrer le fichier dans la base
de données de Git: cela se fait à l'aide de la commande
\mintinline{bash}|git commit|. La syntaxe de cette commande est la
suivante:
\begin{minted}{bash}
git commit <fichier> -m "<message>"
\end{minted}
où \verb|<fichier>| est le nom du ou des fichiers à enregistrer, et
\verb|<message>| une petite ligne susceptible de servir
d'aide-mémoire:
\begin{minted}{text}
[robert@kiddo travail]$ git commit recherche.txt -m "version initiale"
[master (commit racine) fa1ec00] version initiale
 1 file changed, 11 insertions(+)
 create mode 100644 recherche.txt
\end{minted}

\paragraph{Poursuite du travail}
Git enregistre tous les \emph{commits} dans un fichier journal, en
anglais \emph{log file} ou plus simplement \emph{log}. Dans les
exemples qui suivent, nous avons inséré dans le fichier
\verb|recherche.txt| donné \vpageref{ref:recherche} les modifications
correspondant à la deuxième version du fichier.

Comme ce fichier est indexé, la commande \verb|git diff| nous montre
immédiatement quelles sont les différences (v. plus haut
\vpageref{ref:diff}):
\begin{minted}[linenos,escapeinside=||]{text}
[robert@kiddo travail]$ git diff
diff --git a/recherche.txt b/recherche.txt
index 3baf502..f230132 100644
--- a/recherche.txt
+++ b/recherche.txt
|\textcolor{Blue}{@@ -6,6 +6,6 @@}| COMBRAY
 
 I
 
|\textcolor{Red}{-Longtemps, je me suis couché très tôt. Parfois, à peine ma}|
|\textcolor{Red}{-bougie éteinte, mes yeux se fermaient si vite que j'avais juste le}|
|\textcolor{Green}{+Longtemps, je me suis couché de bonne heure. Parfois, à peine ma}|
|\textcolor{Green}{+bougie éteinte, mes yeux se fermaient si vite que je n'avais pas le}|
 temps de me dire: «Je m'endors.»
\end{minted}

Pour terminer, enregistrons ces modifications:
\begin{minted}{text}
[robert@kiddo travail]$ git commit recherche.txt -m "nouvelle version de l'incipit"
[master 83b6c3e] nouvelle version de l'incipit
 1 file changed, 2 insertions(+), 2 deletions(-)
\end{minted}

Et demandons à Git de nous fournir un extrait de son journal:
\begin{minted}[linenos,escapeinside=||]{text}
[robert@kiddo travail]$ git log
|\textcolor{Brown}{commit 83b6c3e6dad72116eac5ce7d1ba70968e4e57ebb}|
Author: Robert Alessi <alessi@robertalessi.net>
Date:   Wed Oct 3 15:05:32 2018 +0200

    nouvelle version de l'incipit

|\textcolor{Brown}{commit fa1ec001efdca9c69cc768dc9cf83706bdb6e603}|
Author: Robert Alessi <alessi@robertalessi.net>
Date:   Wed Oct 3 14:49:10 2018 +0200

    version initiale
\end{minted}

Nous voyons aux lignes~2 et 8 qu'à chaque \emph{commit} est associé un
\emph{numéro de registre}, en notation hexadécimale, formé d'une
séquence de~40 caractères allant de \verb|0| à \verb|9| et de \verb|a|
à \verb|f|.

\subsection{Résumé des commandes}
\label{sec:resume-des-commandes}
\begin{enumerate}
\item \verb|git config --global| $\rightarrow$ paramétrage initial de
  Git.
\item \verb|git init| $\rightarrow$ initialisation de Git dans un
  nouveau répertoire.
\item \verb|git status| $\rightarrow$ demande à Git un \emph{rapport
    d'état}.
\item \verb|git add| $\rightarrow$ indexe des fichiers dans la zone de
  travail. Les fichiers indexés sont ceux qui seront suivis par
  Git.
\item \verb|git commit <fichier> -m "<message>"| $\rightarrow$
  enregistre dans la base de données de Git les versions modifiées des
  fichiers sous forme d'instantanés.
\item \verb|git diff| $\rightarrow$ montre les différences entre la
  version actuelle des fichiers et leur dernière version enregistrée
  par %
  \verb|git commit|.
\item \verb|git log| $\rightarrow$ affiche le journal de Git.
\end{enumerate}

\section{Git en mode graphique}
\label{sec:git-gui}

\hfill\verb|../.. à suivre|

\begin{landscape}
  \begin{figure}
    \centering
    \adjustimage{frame,width=\linewidth}{images/02-gitk.png}
    \caption{gitk}
    \label{fig:gitk}
  \end{figure}
\end{landscape}

\end{document}
