cours-git/cours_git.tex

363 lines
11 KiB
TeX

\documentclass[10pt]{beamer}
\usepackage{ucs}
\usepackage[utf8]{inputenc}
\usepackage[french]{babel}
\usepackage[T1]{fontenc}
\usepackage{graphicx}
\title{Git c'est la vie}
\subtitle{Un cours sur cet outil magique qui s'appelle git}
\author{Francesco Bariatti}
% Put table of contents at the beginning of each section
\AtBeginSection[]
{
\begin{frame}[noframenumbering]{}
\tableofcontents[currentsection]
\end{frame}
}
\usetheme{CambridgeUS}
\usecolortheme{beaver}
\begin{document}
\frame{\titlepage}
\begin{frame}
\frametitle{Plan}
\tableofcontents
\end{frame}
\section{Prérequis}
\begin{frame}[fragile]
\frametitle{Prerequis}
Prérequis pour suivre ce cours:
\begin{itemize}
\item Savoir lire la signature d'une commande \verb#command -a [-b] [-c | -d] --long-arg PARAM1 PARAMS2...#
\item Savoir lire des messages affichés dans la console. Git affiche plein de messages utiles, il faut les lire.
\end{itemize}
\end{frame}
\section{Présentation de git}
\begin{frame}
\frametitle{C'est quoi git}
\begin{columns}[c]
\column{0.5\textwidth}
\begin{block}{}
Git est un logiciel de versioning.
\end{block}
\begin{itemize}
\item Crée par notre modèle spirituel, Linus Torvalds en 2005.
\item Le logiciel de versioning utilisé pour le noyau Linux est devenu propriétaire, donc il en a développé un autre.
\end{itemize}
\column{0.5\textwidth}
\begin{center}
\includegraphics[scale=0.2]{img/linus}
\end{center}
\end{columns}
\end{frame}
\begin{frame}
\frametitle{Ça permet de faire quoi}
\begin{itemize}
\item Ne pas perdre son travail
\item Pouvoir inspecter des versions spécifiques de son travail
\item Travailler à plusieurs
\item Pouvoir donner la faute d'un bug à un collègue (on sait qui a codé quoi)
\end{itemize}
\vspace{2\baselineskip}
\begin{itemize}
\item Git n'est pas un logiciel qui tourne en permanence: chaque commande est un petit processus.
\item Tout est enregistré dans des fichiers
\begin{itemize}
\item Possible d'interrompre le travail à tout moment
\end{itemize}
\end{itemize}
\begin{alertblock}{}
Git fonctionne très mal avec les fichiers binaires
\end{alertblock}
\end{frame}
\section{Le commit}
\begin{frame}
\begin{block}{}
Le commit est l'entité de base de git.
\end{block}
Un commit c'est:
\begin{itemize}
\item Un ensemble de changements (sur un ou plusieurs fichiers)
\item Une date
\item Un auteur
\item \textbf{Un message}: il peut être sur plusieurs lignes!
\item \textbf{Un pointeur vers sont parent}
\item \textbf{Un hash unique} basé sur tout ça (plus ou moins).
\end{itemize}
\begin{alertblock}{}
Les commit doivent raconter une histoire!
\end{alertblock}
\end{frame}
\begin{frame}
\frametitle{Un historique git}
\begin{columns}[c]
\column{0.3\textwidth}
\begin{center}
\includegraphics[height=0.7\textheight]{img/gitrepo}
\end{center}
\column{0.7\textwidth}
\begin{itemize}
\item Historique git: suite de commits (+ pointeur sur dernier).
\item Un fichier existe seulement comme suite de modifications.
\item Un commit non pointé est un commit perdu.
\end{itemize}
\end{columns}
\end{frame}
\begin{frame}[fragile]
\frametitle{Des commandes!}
\begin{itemize}
\item Création d'un projet: \verb|git init DOSSIER| ou \verb|git clone URL [DOSSIER]|
\item Visualisation de l'état (est-ce qu'il y a eu des modifications?): \verb|git status|
\item Visualisation des modifications: \verb|git diff|
\item Ajouter des modifications au prochain commit: \verb|git add FICHIERS...|
\item Créer un commit: \verb|git commit|
\item Voir l'historique: \verb|git log|
\item Voir le log en plus joli: \verb|git log --all --graph --decorate --oneline|
\end{itemize}
\end{frame}
\section{Les branches}
\subsection{Le concept des branches}
\begin{frame}
\frametitle{Ça sert à quoi?}
\begin{itemize}
\item Travailler à plusieurs.
\item Faire plusieurs choses au même temps (nouvelle fonctionnalité, correction de bugs, ...).
\item Essayer des nouvelles choses en parallèle sans impacter le projet: modifications indépendantes sur une même base.
\end{itemize}
\vspace{2\baselineskip}
\begin{itemize}
\item Très facile de basculer de l'une à l'autre: git modifie les fichiers automatiquement.
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{C'est quoi?}
\begin{columns}[c]
\column{0.4\textwidth}
\begin{center}
\includegraphics[height=0.7\textheight]{img/branches}
\end{center}
\column{0.6\textwidth}
\begin{itemize}
\item Branche: pointeur sur un commit
\end{itemize}
\vspace{\baselineskip}
\begin{itemize}
\item Une histoire qui diverge à partir d'un certain commit
\item En se positionnant sur un pointeur ou sur un autre on voit des choses différentes
\end{itemize}
\end{columns}
\end{frame}
\subsection{Le merge}
\begin{frame}
\frametitle{Le merge}
\begin{columns}[c]
\column{0.5\textwidth}
\begin{center}
\includegraphics[height=0.7\textheight]{img/merge}
\end{center}
\column{0.5\textwidth}
\begin{itemize}
\item Intègre les changements d'une branche dans une autre
\item Création d'un commit de merge: commit spécial avec deux parents
\item À partir de la branche de destination (Branche1 dans l'exemple) il est possible de voir l'historique des deux branches.
\item Git fusionne intelligemment les modifications des deux branches
\end{itemize}
\end{columns}
\end{frame}
\begin{frame}
\frametitle{Les conflits de merge :(}
Parfois impossible de fusionner automatiquement: si les deux branches ont modifié le même bout de code.
\begin{block}{}
Le commit de merge peut introduire des modifications: utilisé pour résoudre les conflits
\end{block}
\begin{itemize}
\item Git affiche un message d'erreur en cas de conflit
\item Les conflits sont clairement délimités dans les fichiers à l'aide de chevrons
\item Git présente les deux versions du bout de code et demande à l'humain de choisir la version finale (en modifiant le code et supprimant les chevrons)
\item Il est aussi possible d'abandonner le merge
\end{itemize}
\begin{block}{}
En faisant des petits commits, il est plus simple de repérer quelle modification a introduit le conflit.
\end{block}
\end{frame}
\begin{frame}{Le merge ``fast-forward''}
\begin{columns}
\column{0.5\textwidth}
\begin{center}
\includegraphics[width=\textwidth]{img/fast-forward}
\end{center}
\column{0.5\textwidth}
\begin{itemize}
\item Quand il n'y a pas de modifications à fusionner
\item Le pointeur de branche est simplement modifié
\end{itemize}
\end{columns}
\end{frame}
\subsection*{Les commandes des branches}
\begin{frame}[fragile]
\frametitle{Les commandes des branches}
\begin{itemize}
\item Créer une branche avec comme base le commit courant: \verb|git branch NOM|
\item Créer une branche avec comme base un commit spécifique: \verb|git checkout -b BRANCHE COMMIT|
\item Bouger entre les branches: \verb|git checkout BRANCHE|
\item Fusionner une branche: \verb|git merge ORIGINE [DESTINATION]|
\item En cas de conflit:
\begin{itemize}
\item Modifier les fichiers à la main
\item \verb|git add FICHIERS...|
\item \verb|git commit|
\end{itemize}
\item Abandonner la fusion pendant un conflit: \verb|git merge --abort|
\end{itemize}
\end{frame}
\section{Dépôts distants (remotes)}
\subsection{Explication}
\begin{frame}[fragile]
\frametitle{Les dépôts distants}
Chaque développeur a toujours une \textit{copie intégrale} du projet.
Il est possible d'avoir une telle copie du projet sur un serveur pour mettre en commun le travail.
\begin{block}{}
Une copie de chaque branche du serveur est gardée en local pour pouvoir être inspectée (\verb|origin/branche|).
\end{block}
\end{frame}
\begin{frame}
\begin{columns}[T]
\column{0.5\textwidth}
\begin{center}
\includegraphics[height=0.7\textheight]{img/remotes_non_diverging}
\end{center}
\column{0.5\textwidth}
\begin{center}
\includegraphics[height=0.7\textheight]{img/remotes_diverging}
\end{center}
\end{columns}
\end{frame}
\begin{frame}
\frametitle{Historique commun}
Sur git il est possible de modifier l'historique (réorganiser les commits, les modifier, ...). Même si on ne verra pas comment faire, il faut toujours retenir:
\begin{alertblock}{}
Il ne faut jamais modifier l'historique commun!!!
\end{alertblock}
Tout ce qui a été poussé sur un dépôt distant est commun.
Il ne faut modifier rien qui puisse être atteint à partir d'un commit présent sur le dépôt commun.
\end{frame}
\subsection{Les commandes}
\begin{frame}[fragile]
\frametitle{Les commande des remotes}
\begin{itemize}
\item Récupère les modifications de la branche remote sans les intégrer à la branche courante (= met à jour les branches \verb|origin/*|): \verb|git fetch|
\item Récupère les modifications de la branche remote et les ajoute dans la branche courante: \verb#git pull [ --merge | --rebase ]#
\item Pousse les modifications de la branche courante sur le remote: \verb|git push|.
\begin{itemize}
\item Dans le cas que la branche remote n'existe pas (elle va être crée): \verb|git push -u origin NAME|
\end{itemize}
\end{itemize}
\end{frame}
\subsection{Les techniques de pull}
\begin{frame}
\frametitle{Pull merge (default)}
\begin{columns}[T]
\column{0.5\textwidth}
\begin{center}
\includegraphics[height=0.7\textheight]{img/pull_before}
\end{center}
\column{0.5\textwidth}
\begin{center}
\includegraphics[height=0.7\textheight]{img/pull_merge}
\end{center}
\end{columns}
\end{frame}
\begin{frame}
\frametitle{Pull rebase}
\begin{columns}[T]
\column{0.5\textwidth}
\begin{center}
\includegraphics[height=0.7\textheight]{img/pull_before}
\end{center}
\column{0.5\textwidth}
\begin{center}
\includegraphics[height=0.7\textheight]{img/pull_rebase}
\end{center}
\end{columns}
\end{frame}
\section{Pointeurs avancés}
\begin{frame}[fragile]
\frametitle{Le pointeur HEAD}
\begin{itemize}
\item HEAD est un pointeur sur la situation ``courante'' des fichiers.
\item Il pointe normalement sur la branche courante
\item \verb|git checkout COMMIT_HASH| permet de bouger HEAD à un autre point de l'histoire: les fichiers auront alors le contenu qu'ils avaient à ce moment là.
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\frametitle{Le soft reset}
\verb|git reset COMMIT_HASH| permet de bouger la tête de la branche sur un commit particulier. Il n'y a plus rien qui pointe sur les commits plus récents, \textbf{ils sont alors oubliés}.
Les fichiers ne sont par contre pas modifiés.
\end{frame}
\begin{frame}[fragile]
\frametitle{Le hard reset}
\verb|git reset --hard COMMIT_HASH| permet de bouger la tête de la branche sur un commit particulier, \textbf{en écrasant toutes les modifications faites depuis}.
\begin{block}{}
\verb|git reset --hard HEAD| supprime toutes les modifications faites depuis le dernier commit (donc juste les modifications pas enregistrées dans un commit).
\end{block}
\end{frame}
\frame{\titlepage}
\end{document}