diff --git a/content/projet_programmation/2_git/index.md b/content/projet_programmation/2_git/index.md new file mode 100644 index 0000000..ccf4317 --- /dev/null +++ b/content/projet_programmation/2_git/index.md @@ -0,0 +1,257 @@ + +--- +title: "PdP: Git" +date: 2024-01-17 +tags: ["Internet", "Débit"] +categories: ["Projet de programmation", "Cours"] +mathjax: true +--- + +Les systèmes de contrôles de versions permettent de garder l'ensemble des +changement effectués sur le code source, à plusieurs dévellopeurs de collaborer +(via des opérations de *merge*) et de naviguer dans l'historique d'un projet. +Ils existent depuis 1972 avec l'apparition de *SCCS*, il a été suivi de +plusieurs autres logiciels depuis, open-sources ou propriétaires. + +## Quelques définitions + +## Gestion de l'historique + +Il y a deux façons de voir l'historique dans un système de version: + + 1. Organisé chronologiquement, immuable dans le sens ou il ne peut être + réinscrit(les erreurs aussi...); + 2. Comme partie intégrante de la documentation. Ainsi il est possible de + comprendre comment et pourquoi on en est arrivé là. Il est alors permis de + le réécrire afin de le clarifier par exemple. + +### Définitions + +**Dépôt** (*repository*): endroit ou est stockée l'historique complet d'un +projet. Il contient l'ensemble des métadonnées du projet. + +**Copie de travail** (*working copy*): une *snapshot* prise depuis le *dépôt* et +sur laquelle travailler. + +## Les paragigmes : centralisé ou distribué. + +Dans un environnement centralisé ou le serveur regroupe toutes les sources et +faisant office de référentiel. + +Dans un environnement distribué ou *décentralisé*, un système de connexion pair +à pair est utilisé. Ainsi le dépôt est présent sur les machines des dévellopeurs +et éventuellement su run ou plusiers serveurs. + +## git + +C'est le système de gestion de version le plus utilisé. Il a été créé par Linux +Torvald, créateur mainteneur du noyau Linux. + +L'utilisation de *git* se fait d'abord en ligne de commande : + +```shell +$ git --stat --after="yesterday" bugfix +# +``` + +La commande contient des options et des aguments en fonction des actions à +effectuer. *Git* permet tout un ensemble de commandes, en voici quelques +exemples: + +```shell +# initialiser un nouveau dépôt +$ git init + +# ajouter un fichier +$ git add moncode.c + +# effectuer un commit +$ git commit -m "Ajour de la fonctionnalité X" +``` + +*Git* propose une aide en ligne accessible via la commande `help` ou des manuel +via lacommande `man`: + +```shell +$ git help +# ou +$ git --help + +# Et via les manuels +man git- +``` + +Il est possible de configurer git globalement (pour tous les projets) ou par +projet. La configuration se fait en ligne de commande : + +```shell +# configuration dans un projet, locale +$ git config --local user.name "John Doe" +$ git config --local user.email j.doe@anonymous.de +$ git config --local core.editor nvim + +# configuration blobale +$ git config --global user.name "John Doe" +$ git config --global user.email j.doe@anonymous.de +$ git config --global core.editor nvim +``` + +La configuration **locale prend le pas sur celle globale**. La configuration est +elle même stockée dans un fichier texte au format *ini*. La liste de toutes les +clés de configuration définie s'obtient avec la commande `git config --list`. + +### L'index + +Physiquement, l*index* est un fichier stocké dans le répertoire `.git` à la +racine du projet. Il contient une liste de chemin vers des ficiers avec leurs +permissions et le condensat *SHA1* de l'objet en question. + +Les fichiers stockés dans notre index on 6 états répartis en 3 catégories : + + 1. La copie de travail: + * *Untracked Files*: les fichiers non suivis par git; + * *Unmodified Files*: les fichiers suivis par git mais non modifiés; + * *Modified Files*: les fichies suivis et modifiés. + 2. Métadonnées: + * `staging area`: stocke l'ensemble des modifications temporaires et + plannifiées pour le commit + (dans `.git/index`); + * `local repository`: garde l'intégralité de l'historique (dans + `.git/objects`). + 3. Le réseau + * `Remote Repository`: l'endroit où l'ensemble du travail des dévellopeurs + est synchronisé. + + +L'état courant de l'index s'obtient avec la commande `status`. Il est possible +de vois les 3 états de notre *copie de travail*, voici un exemple sur le dépôt +de mes notes de cours: + +```shell +$ git status +On branch main +Your branch is up to date with 'origin/main'. + +Untracked files: + (use "git add ..." to include in what will be committed) + content/projet_programmation/ + +nothing added to commit but untracked files present (use "git add" to track) +``` + +Les deux commandes principales interagir avec l'index en ajoutant du contenu +sont `add` et `mv` comme le montre le diagramme ci-dessous: + +``` ++-----------+ | +------------+ | +----------+ | +---------+ | +------------+ | +-------------+ +| Untracked | | | Unmodified | | | Modified | | | Staging | | | Local repo | | | Remote repo | ++-----------+ | +------------+ | +----------+ | +---------+ | +------------+ | +-------------+ + | | | | | + >-----------------(git add)--------------------> | | + | | | | | + | | >---(git add)---> | | + | | | | | + | >-----------(git mv)-----------> | | + | | | | | + | | >----(git mv)---> | | + | | | | | +``` + +Les commandes `rm` et `reset` permettent de supprimer du contenu. +`git rm -r ` permet de supprimer récusivement un repertoire et +`git rm --cached ` supprime un élément des fichiers suivis sans pour +autant supprimer le supprimer du disque: + +``` ++-----------+ | +------------+ | +----------+ | +---------+ | +------------+ | +-------------+ +| Untracked | | | Unmodified | | | Modified | | | Staging | | | Local repo | | | Remote repo | ++-----------+ | +------------+ | +----------+ | +---------+ | +------------+ | +-------------+ + | | | | | + <-----------------(git rm)---------------------< | | + | | | | | + <--------(git rm --force)--------< | | | + | | | | | + <----(git rm)---< | | | | + | | | | | + | | <--(git reset)--< | | + | | | | | + | <------(git reset --hard)------< | | +``` + +### Ignorer des fichiers + +Un projet peut contenir un ensemble de fichiers que ne doivent pas être suivi +comme par exmeple les fichiers object issus de la compilation ou encore les +binaires. + +Git propose un mécanisme pour ignorer ces fichiers via un fichier que se soit +globalement via `~/.config/git/ignore` ou par projet avec `.gitignore` racine. + +Voici un exemple: + +```.gitignore +# All .o files +*.o + +# all the content into build/ +**/build + +# but the text file mus be tracked +!build/*.txt +``` + +Il est trs important **de maintenir une liste à jour des fichiers ignorés** afin +de laisser le dépôt le plus propre possible. On évite ainsi le bruit initile +dans notre dépôt et ainsi d'oublier de mettre dans le stage un fichier importan +noyé dans la liste des fichier non-suivi. + +### Gestion de l'historique + +Chaque *commit* est identifié par un condensat `SHA1` calculé sur l'arbre des +chagements (arbre de Merkel). L'historique des changements effectués est +accessible par la commande `git log`. Voici quelques exemples: + +```shell +# version courte ... +$ git log --oneline + +# version courte avec des stats +$ git log --oneline --stat + +# en version patch +$ git log --patch +``` + +Écrire des messages de commit cohérent permet de garder un historique propre et +de documenter les changements effectués. Un commit peut contenir plusieurs +lignes cependant la première doit être inférieure à 50 lignes, il est conseillé +de limiter les suivantes à 72 caractères. +doivent avoir 72 caractères + +#### Se balader dans l'historique + +La commande `checkout` permet de se ballader dans l'historique alors que +`commit` permet de rajouter un point dans l'historique. *git c + +``` ++-----------+ | +------------+ | +----------+ | +---------+ | +------------+ | +-------------+ +| Untracked | | | Unmodified | | | Modified | | | Staging | | | Local repo | | | Remote repo | ++-----------+ | +------------+ | +----------+ | +---------+ | +------------+ | +-------------+ + | | | | | + | | | >--(git commit)--> | + | | | | | + | | >-------(git commit --all)-------> | + | | | | | + | <-----------(git checkout HEAD)-----------------< | + | | | | | + | <--------(git checkout)--------< | | + | | | | | +``` + +#### Les branches, tags + +Pour les branches, ous en utilisons une les dès que nous initialisons notre +dépôt, souvent appelée `master` ou `main`. Elle représentent une référence vers +une suite de commits. Cette référence évolue lors de l'ajout de commit. + +Un tag est lui une référence vers un commit précis qui n'évolue pas.