257 lines
9.8 KiB
Markdown
257 lines
9.8 KiB
Markdown
|
|
---
|
|
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
|
|
# <options > <args>
|
|
```
|
|
|
|
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 <commande>
|
|
# ou
|
|
$ git <commande> --help
|
|
|
|
# Et via les manuels
|
|
man git-<commande>
|
|
```
|
|
|
|
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 <file>..." 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 <dir>` permet de supprimer récusivement un repertoire et
|
|
`git rm --cached <file>` 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.
|