Programmation Web Avancée

Cours 7
git logo
npm logo

kn@lri.fr

Git

Rappels : DAG

Directed Acyclic Graph : graphe orienté acyclique.


dag

git

git est un système de contrôle de version distribué (DVCS) :

Utilité :

Historique

git par l'exemple

D'autres références :

Dépôt git (ou projet)

Un dépôt est une collection de fichiers se trouvant dans un répertoire et dont les modifications sont suivies par git

$ mkdir my-project $ cd my-project $ git init Initialized empty Git repository in …/my-project/.git/ $ ls -a . .. .git/

Tout les fichier que l'on veut suivre doivent être dans ce répertoire, ou un sous répertoire

La commande git status permet de connaître l'état du dépôt

commit (1)

Un commit est un instané de tous les fichiers du dépôt et de leur contenu à un instant donné, plus des méta-données (date, nom de la personne qui a crée le commit, …). Les commits sont crées en deux temps :

  1. ajout des fichiers modifiés que l'on souhaite au prochain commit
  2. validation du commit
$ emacs README.md #ou n'importe quel autre éditeur de texte $ git add README.md $ git status … Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: README.md $ git commit #lance l'éditeur par défaut [master (root-commit) 71dda77] Ajout du premier fichier. 1 file changed, 1 insertion(+) create mode 100644 README.md

commit (2)

git ne possède pas de commande spéciale pour ajouter un fichier au dépôt. Ajouter un fichier, ou modifier un fichier existant se font de la même manière

⚠️ git ne peut stocker que des fichiers et leur chemin. En particulier, on peut pas ajouter un répertoire vide dans un dépôt git.

Un commit est identifié de manière unique par son hash (somme de contrôle).

git utilise l'algorithme SHA-1 : les hash font 160 bits (20 octets ou 40 chiffres hexadécimaux).

La commande git show abcde… permet de montrer l'objet git (commit mais aussi d'autres) dont le hash est donné. On n'est pas obligé de donner les 40 caractères, un prefixe suffit.

Historique (1)

git garde un historique des modifications faites à un dépôt.

Chaque commit pointe vers son parent et le hash du parent est pris en compte dans le calcul du hash du commit.
⇒ Impossible de falsifier un « commit » dans l'historique

$ emacs README.md $ emacs test.js $ git add test.js README.md $ git commit [master 30d4a5d] Ajout du fichier principal. 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 test.js $ git log #affiche les commits

Historique (2)

Un commit git n'est pas un diff d'une version du fichier à l'autre. C'est l'ensemble des fichiers tels qu'ils étaient à un moment donné.
git stocke ces « images instantanées » de manière compacte.

Historique (3)

L'ensemble des commit d'un projet git forme un DAG :

$ emacs test.js $ git add test.js $ git commit

Branches (1)

Sauf cas particulier, on est toujours sur une branche, i.e. sur un chemin nommé entre le commit courant et le commit initial

La branche principale, crée par défaut se nomme master

$ git branch * master

Il est possible d'avoir plusieurs branches (pour faire des essais, corriger des bugs, …) sans toucher à la branche principale.
La commande git branch foo crée une nouvelle branche appelée foo à partir du commit courant.

$ git branch fibonacci $ git branch fibonacci * master

Branches (2)

Chaque branche se souvient de son dernier commit
On peut changer de branche avec git checkout ma_branche

$ git checkout fibonacci Switched to branch 'fibonacci' $ emacs test.js $ git add test.js $ git commit $ emacs README.md $ git add README.md $ git commit

Branches (3)

Deux branches sont complètement indépendantes et peuvent évoluer en parallèle:

$ git checkout master Switched to branch 'master' $ emacs README.md $ git add README.md $ git commit

merges

Une opération de merge (fusion) consiste à importer les modifications d'une branche dans une autre. Pour cela :

  1. On se place dans la branche de destination (avec git checkout ma_branche)
  2. On effectue git merge branche_source
$ git checkout master Switched to branch 'master' $ git merge fibonacci Auto-merging README.md CONFLICT (content): Merge conflict in README.md Automatic merge failed; fix conflicts and then commit the result.

git essaye de fusionner les deux branches automatiquement. La plupart du temps il y arrive. Si un même fichier est modifié de deux manière différentes, il y a un conflit.

Conflits

Un conflit dans un fichier est simplement matérialisé par une section :

<<<<<<< HEAD du texte ======= une autre version >>>>>>> branche_source

La portion du haut est le texte de la branche cible (sur laquelle on est) et celui du bas celui de la branche source.
Il faut retirer toutes les sections qui ont cette forme (en choisissant l'une ou l'autre des versions, ou encore une troisème), puis commiter.

$ emacs README.md #on règle le conflit $ git add README.md $ git commit [master e01a960] Merge branch 'fibonacci'

Dépôt distant (1)

Pour récupérer un projet git déjà existant, on utilise la commande git clone :

$ git clone https://gitlri.lri.fr/kim.nguyen/js

De telles URL sont appelées « remote »
L'URL source initiale est appelée origin.

Pour synchroniser le projet local avec un remote on utilise git pull et git push.

git pull [nom-de-remote-ou-url]
récupère l'état de la même branche dans la repository distante et la merge dans la branche courante

git push [nom-de-remote-ou-url]
merge la branche courante dans la branche de même nom de la repository distante

Dépôt distant (2)

En réalité, un dépôt git (local) possède :

$ git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/fibonacci remotes/origin/master

La commande git pull est en fait un alias pour :

  1. git fetch : synchronize la branche mirroir locale de chaque remote
  2. git merge de la branche mirroir locale dans la branche locale

Dépôt distant (3)

En fonction de l'état des dépôt distants, les commandes git pull ou git push peuvent créer des conflits :

Plein d'autres outils …

git log
affiche l'historique
git log --graph
affiche l'historique avec le graphe de commits
git diff
Affiche la différence entre deux commits donnés
git bisect
Permet de trouver une régression introduite par un commit

Fichier à ne pas mettre sous git

Certains fichiers peuvent être présents mais ne doivent pas être versionnés :

On peut créer dans tous lse sous-répertoire du dépôt (et aussi à la racine) un fichier .gitignore qui contient les fichiers à ignorer. Git ne se plaindra pas de leur existance et interdira de les commiter par erreur.

github et compagnie ?

Il existe de nombreux services autour de git. Ils ne sont pas nécessaire à l'utilisation de git pour un projet, mais offre des avantages :

On fera cepdant garde, les remarques usuelles sur la souveraineté des données s'appliquent.

npm

Gestion des dépendences

On a un programme p qui a besoin d'une bibliothèque l pour s'exécuter (liaison dynamique). Comment est-ce géré par les différents systèmes ?

Linux (la plupart des distributions)
Un système de packages avec de dépendences. Installer p via le système de package force l'installation de l
Windows
L'installeur du programme installe l.dll dans un répertoire système.
OS X
Une « application » OS X est en fait un répertoire contenant les ressources et toutes les dépendences nécessaires au programme.

Quels sont les avantages et inconvénients ?

Gestion des dépendences Linux

Avantages

Inconvénients

Gestion des dépendences OS X

Avantages

Inconvénients

Gestion des dépendences Windows

Avantages

Inconvénients

DX_D9.DLL is missing…

Bibliothèques nodejs

nodejs est multi-plateforme. Comment installer des bibliothèques Javascript et les utiliser ?

npm logo

npm

Node Package Manager est un programme qui permet :

npm init

La commande npm init initialise le répertoire courant comme un projet nodejs. Elle pose diverse questions, le résultat est sauvé dans package.json.

npm install

On peut installer un paquet au moyen de la commande npm install le-paquet.

$ npm install colors #permet d'écrire en couleur dans la console

Dans le fichier Javascript

const colors = require ('colors/safe'); console.log(colors.rainbow("Hello, world!"));

La dépendence a été enregistrée dans package.json. On peut passer des options à npm install

-G
(global) installe dans le répertoire système et non pas dans le répertoire ./node_module (nécessite les droits administrateurs).
--save-dev
le paquet installé est une dépendence de développement, pas d'exécution (l'utilisateur final n'en a pas besoin)

npm et git

Le répertoire node_modules/ doit être ajouté au fichier .gitignore, son contenu ne doit pas être ajouté au dépôt.

Lorsque quelqu'un git clone un projet npm il n'a pas les dépendences. Il faut faire npm install dans le dépôt cloné pour les télécharger (à partir de .json)

Problèmes de npm

Problèmes de npm

$ npm install ascii-art $ du -sh node_modules 15M node_modules/ $ ls -d node_modules/* | wc -l 117

Dans le fichier Javascript

const aa = require ('ascii-art'); aa.font("Hello, world!", "Doom", (result) => { console.log(result); });

npm : horror story (1)

  1. Un programmeur open-source publie un paquet npm nommé kik
  2. L'entreprise kik.com (logiciel de messagerie) demande au programmeur de renommer le paquet (copyright)
  3. Le programmeur refuse
  4. npmjs.org donne raison à l'entreprise
  5. En protestation, le programmeur supprime ses paquets dont left-pad, un paquet contenant une unique fonction de 11 lignes qui rajoute des blancs devant une chaîne.
  6. L'Internet se casse pendant plusieurs heures

npm : horror story (2)

  1. Un programmeur open-source publie un paquet npm nommé event-stream
  2. Après plusieurs mois sans release, un autre programmeur contacte l'auteur pour proposer d'assurer la maintenance, l'auteur accepte
  3. Le nouveau mainteneur rajoute discrètement du code pour voler des bitcoins lorsqu'une page qui charge event-stream se connecte à un porte monnaie virtuel.

npm : bilan

Avantages

Inconvénients

Éviter absolument d'importer des packages comme is-number

privilégier les paquets avec peu ou pas de dépendences.

Auditer un minimum les paquets importés