Le but de cette UE en ligne est de vous familiariser avec les outils informatiques que vous allez devoir utiliser au cours de l’année.
Ça commence par le terminal et la ligne de commande, puis SSH et la pratique du cryptage de vos communications, puis VPN et la connexion à distance sur les machines de TP, puis le gros morceau : git et la gestion de versions et gitlab.
Cette UE est minimaliste. L’intention est de vous donner le minimum vital pour naviguer. Vous aurez des compléments plus tard dans différentes UEs.
Cette UE est prévue pour rattraper un manque d’information sur ces sujets par certains élèves. Si vous savez déjà, survolez la section.
Cette UE est autoévaluée, mais soyons clairs : comprendre ces notions est obligatoire, sans quoi vous allez souffrir pendant les années à venir.
Auteur : Jean-Claude Dufourd, Télécom Paris
Les transparents sont groupés par chapitre.
Si vous avez besoin de soutien, je serai disponible des mercredis à la pause déjeuner et pendant le projet :
Pendant la pause déjeuner (12h-13h30) je serai dans la salle 5B01. De 13h30 à 16h45, je serai soit dans cette salle, soit dans une des salles du projet Artefact. Aussi disponible par zoom à d’autres moments, me demander
Sur terminal, SSH et VPN, tous les enseignants peuvent vous aider. Sur git et gitlab, demandez leur.
A l’origine, les ordinateurs n’ont pas de terminal, clavier, écran, mais un lecteur de ruban ou cartes perforées et une imprimante. Un programme est un paquet de cartes perforées ou un ruban qu’on met dans le lecteur, et quand l’ordinateur a fini le programme précédent, il lit le prochain paquet de cartes, exécute le programme et imprime les résultats. Le système d’exploitation est extrêmement simple.
A Télécom en 1985, j’ai déposé un paquet de cartes dans un casier du centre de calcul et j’ai récupéré le rapport le lendemain. |
Le clavier est apparu pour taper des commandes dont le résultat était imprimé.
Les premiers écrans ressemblent aux radars dans les vieux films noir et blanc. Ils servent plus à afficher des informations graphiques qui ne passent pas sur des imprimantes de type « machines à écrire ».
Puis apparaissent les premiers terminaux avec un écran alphanumérique et un clavier. C’est à cette époque que se développe le système d’exploitation qui est à la base de ce que nous utilisons aujourd’hui : Unix.
A Télécom en 1985, les chercheurs avaient déjà des claviers, des écrans, mais pas de souris. Je possédais un PC avec 640Ko de RAM, avec un disque dur de 5Mo et une souris !
Sur un écran graphique actuel, une fenêtre alphanumérique remplace l’écran cathodique d’origine, et le clavier est temporairement attaché à cette fenêtre par un clic de la souris.
Le terminal vient donc du fonctionnement d’origine des ordinateurs. Il reste un outil précieux pour ce qui est administration de l’ordinateur.
Le principe est le même que sur un terminal d’origine : vous tapez une commande, elle est exécutée, et le résultat est affiché sur l’écran en dessous de la commande au lieu de l’imprimante.
Selon le système d’exploitation, les commandes varient. MacOS et Linux, tous les deux basés sur Unix, ont un ensemble de commandes de base très proches. Windows a un terminal DOS avec des commandes très différentes et en fait très primitives, et aussi depuis peu un terminal dit PowerShell inspiré de Linux.
Le programme qui lit les commandes que vous tapez dans le terminal s’appelle le « shell ». Il lit la commande, la vérifie, va chercher le programme à exécuter, le lance, récupère le résultat et l’affiche. Il y a malheureusement beaucoup de variantes de shell.
Avant d’aller plus loin et de vous montrer des exemples, j’ai besoin de vous parler des fichiers et du système de fichiers.
Un disque est un appareil permettant de stocker des données informatiques. Originellement sous forme de disques magnétiques qui tournaient dans des boites sous vide, l’appellation disque est moins pertinente aujourd’hui avec les SSD qui sont de simples mémoires.
Un disque physique est organisé en « volumes » qui ne sont rien d’autres que des zones séparées du disque physique. Les données des fichiers sont organisées d’une certaine manière, c’est-à-dire leur format (HFS+, NTFS, FAT…). Certains formats sont plus faciles à lire sur certains systèmes mais dans le principe, ils rendent tous le même service : organiser les fichiers d’un volume en dossiers et sous-dossiers (directory ou folder en anglais) et gérer l’espace libre.
Un dossier est une liste de fichiers et de sous-dossiers. Il peut y avoir beaucoup de niveaux de sous-dossiers.
Un fichier est un paquet de données avec des caractéristiques diverses : un type de données (texte, image), une date de création, un auteur, un type d’encodage (US, FR, JP), un format (JPEG, PNG, Word), une localisation sur le disque, c’est-à-dire dans quel volume et quel dossier.
Pour naviguer un disque et trouver un fichier, vous pouvez utiliser Finder sur MacOS, Nautilus sur Linux et Explorer sur Windows, qui sont des logiciels graphiques pour consulter le contenu d’un volume.
Nous verrons des exemples dans les vidéos sur les terminaux mais une différence importante est la façon d’écrire les dossiers :
Vous disposez d’un espace de stockage de fichiers à l’école. Cet espace est sauvegardé. Il est disponible automatiquement sur toutes les machines de TP de l’école. Quand vous êtes connecté.e.s sur une de ces machines (Linux), le dossier home est votre espace.
Vous pouvez accéder à cet espace de stockage depuis un PC en vous connectant sur \samba.enst.fr_login
Vous pouvez accéder à cet espace de stockage depuis un Mac en vous connectant sur smb:\samba.enst.fr_login
Votre machine personnelle doit être connectée sur le wifi Campus-Télécom ou utiliser le VPN (voir plus loin).
Nous avons maintenant tous les éléments pour vous montrer des exemples d’utilisation des terminaux.
Choisissez votre système d’exploitation préféré pour voir la démo.
Pour exécuter un programme, vous devez soit connaitre sa localisation sur le disque, soit juste son nom si le programme est dans le chemin d’accès.
Un programme est installé dans un dossier. Ce dossier peut être un dossier du système pour les programmes qui appartiennent au système d’exploitation. Ce dossier peut être un dossier particulier juste réservé à ce programme, surtout si ce programme a des ressources dont il a besoin. Dans ce dernier cas, l’installation du programme sur votre machine revient à créer le ou les dossiers dont ce programme a besoin sur votre machine et à y mettre toutes les ressources nécessaires, ce qui peut inclure des images, des polices, de la documentation, etc.
Le « shell » (programme qui lit vos commandes et les interprète) a un chemin d’accès où il va chercher les commandes. Le chemin d’accès est une liste de dossiers contenant des programmes. Le shell lit votre commande, isole le nom du programme, va voir dans tous les dossiers s’il trouve ce programme et le lance avec les arguments que vous avez donnés.
Voyons quelques exemples dans votre OS préféré.
Dans le terminal, vous avez un historique des commandes passées, accessible avec les touches curseur vers le haut et vers le bas. Avec les touches curseur vers la droite et vers la gauche, vous pouvez éditer une commande passée pour la modifier, puis appuyer sur retour chariot ou enter pour l’exécuter.
Toujours dans le terminal, la touche tab permet dans les shells modernes de compléter le mot courant : par exemple, vous voulez afficher un fichier texte du dossier courant dont le nom commence par a, tapez « cat a » puis appuyez sur tab qui complètera le nom du fichier s’il n’y a pas d’ambiguité.
Tout ceci a été démontré dans les vidéos précédentes, c’est rappelé ici pour insister.
En plus de cd
, pwd
et ls
:
mkdir x
: créer un sous-dossier xrm x
: supprimer le fichier xmv x y
: renommer le fichier ou dossier x en yrmdir x
: supprimer le dossier x qui doit être
viderm -r x
: supprimer le dossier x et son contenu,
l’argument -r signifiant “récursif”Et en même temps, tout cela peut être fait dans l’outil graphique de consultation des fichiers de votre système d’exploitation.
Le prochain transparent montre une démo de tout cela sur Mac.
Il y a des fichiers qui sont « cachés ». Ce sont des fichiers qui
servent à vos programmes, mais que vous n’avez normalement pas besoin de
voir, sauf accident. Ce sont par exemple les fichiers dont le nom
commence par un point. Pour les voir, il faut ajouter une option à
ls
Les noms de fichier peuvent contenir des espaces. Dans ce cas, le shell prend le nom du fichier comme 2 (ou plus) noms séparés. Pour que le shell comprenne un nom de fichier avec espaces, il faut entourer le nom du fichier par des guillemets ou des apostrophes (” ou ’)
S’il manque un ” ou ’ dans une ligne, alors le shell attend le ” ou ’ manquant indéfiniment : faites controle-C pour en sortir.
.
est le dossier courant, ..
est le dossier
parent, ~
est le dossier racine de l’utilisateur
connecté
/home/dufourd/test/src
est un chemin absolu,
~/test/src
est le chemin équivalent relatif à mon dossier
racine
cd
(tout seul) me remet dans le dossier racine (sauf sur
Windows)
Dans mon dossier racine, test/src
est le chemin relatif
équivalent au chemin absolu /home/dufourd/test/src
/home/dufourd/test/src
fonctionne où que vous soyez,
~/test/src
aussi, mais un chemin relatif dépend d’où vous
êtes
date
: affiche la datewhoami
: affiche le nom du compte connectéwho
: qui est connecté sur cette machinehostname
: affiche le nom de la machinehistory
: affiche l’historique des commandes shellman x
: affiche le manuel de la commande xclear
: efface le terminalcat x
: affiche le contenu du fichier x comme si c’était
du texte (si c’est du binaire, alors ça fait n’importe quoi)less x
: affiche le contenu du fichier x comme si
c’était du texte et page par page; espace pour avancer, et q pour
sortirEn faisant ls -l
vous pouvez voir les permissions des
fichiers.
Pour changer les permissions:
chmod <permission> <fichier>
. Par exemple,
changer un fichier de clef SSH qui est .rwxrwxrwx
, faire
chmod 700 id_ed25519
Les permissions sont: r=lecture w=écriture x=executable. Les premiers RWX sont pour l’utilisateur, puis le groupe, puis tout le monde. 700= RWX pour l’utilisateur, rien pour les autres. 777=RWX pour tout le monde. 640= RW utilisateur, R groupe, rien pour les autres. Le premier caractère des permissions est un d (pour un dossier) ou un . (pour un fichier)
Changer un fichier texte pour qu’il devienne executable:
chmod +x script.sh
. Faites man chmod
pour
connaitre les détails.
Pour savoir ce qui prend de la place sur votre compte, la commande
du
affiche la taille des fichiers et dossiers. Par défaut,
l’unité est le bloc de 512 octets, donc ajoutez toujours l’option
-k
pour avoir des Ko.
du -k
donne l’occupation du dossier courant et de tous
les sous-dossiersdu -s -k
donne juste l’occupation du dossier
courantdu -s -k *
donne l’occupation de tous les sous-dossiers
(un par un)ncdu
est une application interactive plus sympa que du
mais qui n’est pas toujours installéeQuand je me connecte à l’école depuis chez moi, je rentre dans un système où j’ai besoin de m’authentifier pour avoir accès à certaines données sensibles. Le moyen habituel d’authentification est le login et mot de passe. Quand je me connecte, mes informations de connexion transitent sur ma machine, sur la connexion réseau entre ma machine et celle de l’école et sur la machine de l’école. Si un pirate écoute ma machine, le réseau ou la machine de l’école, il peut se faire passer pour moi.
Je suppose que l’école est protégée contre les pirates par le travail de la DSI. Ma machine est protégée des pirates par divers logiciels. Par contre, le réseau entre chez moi et l’école est un espace que je ne contrôle pas. Il pourrait y avoir une machine qui écoute tout ce qui passe sur le réseau pour détecter ce qui ressemble à un login et mot de passe. Par exemple, il est facile de faire cela dans l’école en installant WireShark sur ma machine. Si pendant que j’écoute, quelqu’un se logge sans sécurité, je peux capturer son login et mot de passe.
SSH est un moyen de sécuriser ses communications.
Je vais laisser les explications techniques à une UE réseau future. Ce que vous avez besoin de savoir sur SSH est :
Pour installer une communication SSH, il faut donc :
Pour créer une paire de clefs, la meilleure option est ED25519 (pas DSA, pas RSA, pas ECDSA). La clef obtenue est plus courte et beaucoup plus solide.
Lors de la création de la clef, vous avez le choix de mettre un mot de passe sur la clef privée. Je vous recommande de mettre un mot de passe, même si ce n’est pas obligatoire. Si votre machine est volée ou piratée, sans mot de passe, le pirate peut se connecter partout.
Quand vous ajoutez une clef publique dans le fichier authorized_keys, attention à ne pas ajouter de ligne vide avant ou après votre clef publique, à coller une clef publique entière et rien d’autre… Si le fichier authorized_keys n’est plus de la bonne forme, la connexion ssh ne fonctionnera plus sur cette machine.
Dans tous les cas la commande est :
ssh-keygen -o -a 100 -t ed25519 -f .ssh/id_ed25519 -C "you@telecom-paris.fr"
Dans la vidéo, j’utilise le nom de fichier ed
qui n’est
pas un des noms par défaut, ce qui est moins pratique (merci à Marc pour
la remarque)
Par rapport au mot de passe de la clef:
N’utilisez pas putty qui génère des fichiers dans un autre format.
Lancez la commande ci-dessus directement au bon endroit, à savoir votre dossier .ssh.
Pour se connecter à une machine, par exemple ssh.enst.fr, il faut
exécuter dans le terminal, avec nom-23
votre login ecole
(il y a parfois la première lettre de votre prénom devant votre nom ou
votre nom peut être abrégé) :
ssh nom-23@ssh.enst.fr
Dans ce cas, il vous demande votre mot de passe. La premiere fois, vous devez utiliser le mot de passe.
Si vous installez votre clef publique dans
.ssh/authorized_keys
sur la machine sur laquelle vous vous
connectez (raspberry PI), alors la prochaine fois, vous pourrez faire
:
ssh -i .ssh/id_ed25519 nom-23@ssh.enst.fr
Cette instruction dit à ssh d’aller chercher la clef privée dans .ssh/id_ed25529, à remplacer par le nom de votre clef privée. Dans ce cas, il ne demande pas votre mot de passe du compte et vous connecte directement. Si vous avez mis un mot de passe sur la clef privée, il vous demande votre mot de passe pour la clef.
Pour quitter une session ssh, faites logout
ou tapez
controle-D
Il est possible de grandement fluidifier l’usage de ssh en ajoutant un fichier texte nommé config dans le dossier .ssh.
Contenu du fichier config :
Host *
AddKeysToAgent yes
IdentitiesOnly yes
Host gitlab.enst.fr
PreferredAuthentications publickey
IdentityFile ~/.ssh/<le nom de votre clef privée>
Ce fichier dit:
Donc au premier clone, push ou pull, ça vous demande le mot de passe, puis plus jamais jusqu’au prochain reboot de votre machine.
Pour utiliser vos clefs depuis une machine distante à laquelle vous vous connectez avec ssh, vous avez le choix:
Si vous ajoutez au fichier config dans votre dossier .ssh sur votre machine les lignes :
Host robotpi-XX.enst.fr
ForwardAgent yes
Alors, quand vous êtes connecté sur robotpi-XX.enst.fr
depuis votre machine configurée comme cela, alors la machine
robotpi-XX.enst.fr
fonctionne comme si elle était
configurée en SSH comme votre machine. git clone ...
ou
git pull
vont fonctionner comme si depuis votre
machine.
Ces URLs ne sont visibles que dans l’école ou avec le VPN connecté:
Si vous n’avez pas encore le VPN installé/connecté, prenez le temps de suivre les instructions de la DSI montrées dans le transparent précédent
Une fois connecté avec le VPN, puis ayant trouvé une machine disponible, je peux utiliser l’application Microsoft Remote Desktop (disponible sur Windows, MacOS, iOS, Android) pour me connecter sur la machine.
Sur Ubuntu Linux, ouvrez un terminal, installez Remmina :
sudo apt install remmina
Puis executez remmina après connexion au VPN de l’école, et choisissez une machine pour vous connecter.
Ajoutez .enst.fr
au nom de la machine que vous trouvez
sur tp.telecom-paris.fr .
Attention, sous windows, la souris est décalée vers la droite (de la taille d’un bouton standard) alors que c’est OK sous linux.
Le VPN connecté fait virtuellement migrer votre machine dans l’école, ce qui peut vous empêcher de vous servir de certains services normalement accessibles depuis chez vous, mais interdits par l’école.
Une solution est d’utiliser un tunnel SSH depuis l’extérieur pour vous connecter à une machine interne à l’école, par exemple :
ssh -J dufourd@ssh.enst.fr ubuntu@labgrader.r2.enst.fr
Avec cette instruction, j’ouvre un terminal sur la machine labgrader.r2.enst.fr qui est une machine virtuelle d’INFRES, dont le port SSH n’est pas visible de l’extérieur, en passant par la machine ssh.enst.fr qui est faite pour les tunnels.
Prenons un peu de recul sur tout ce que vous venez de voir.
Vous avez ouvert un terminal sur votre machine :
Vous avez ouvert un terminal sur votre machine, puis lancé une connexion SSH sur une autre machine
Vous avez lancé dans une fenêtre graphique un remote desktop: c’est comme si vous étiez sur l’autre machine, vous pouvez tout faire comme en local.
Note: vous ne pouvez pas faire cela sur une Raspberry PI, vous pouvez seulement faire une connexion SSH/terminal
Vous avez sur votre machine tout le confort d’édition auquel vous avez l’habitude.
Dans un terminal, vous n’avez que des éditeurs de texte frustes.
Pour éditer des fichiers sur votre machine à exécuter sur une autre machine, vous avez deux solutions :
git
sur votre machine et sur l’autre
machine (voir plus loin), et vous faites des suites de
git push
et git pull
sshfs
qui vous permet de partager un
disque de donnée à distance : vous connectez le disque de l’autre
machine à votre machine locale avec le logiciel sshfs
. Les
données sur Raspberry PI apparaissent alors comme si elles étaient sur
une clef USB sur votre machine, vous pouvez les éditer dans votre
environnement et les modifications sont visibles de suite sur la
Raspberry.Sur mac :
/Volumes/distant
sudo sshfs username@machine:/remote/directory /Volumes/distant
(machine est le nom de l’autre machine, username est le nom de
l’utilisateur sur l’autre machine)/Volumes/distant
Sur Linux :
sshfs
avec
sudo apt install sshfs
/media/distant
sudo sshfs -o allow_other,default_permissions username@machine:/remote/directory /media/distant
/media/distant
Sur Windows :
WinFsp et sshfs-Win
depuis https://github.com/winfsp/sshfs-win\\sshfs\username@remote\remote\directory
dans l’explorateur
de fichiersGit est un outil incontournable pour l’ingénieur, même non informaticien. Que ce soit pour des logiciels ou des documents issus d’une collaboration, Git s’est imposé comme la norme.
Gitlab/Github sont des serveurs Git qui gèrent le stockage, le partage entre utilisateurs, les autorisations d’accès et puis toute une couche d’outils supplémentaires qui complexifient énormément leur interface. La partie de l’interface juste pour faire du Git est “assez” simple.
Il est important de réaliser que si vous êtes bloqués en git pour quelque raison que ce soit, vous devez consacrer du temps à vous débloquer, en demandant de l’aide, en continuant à vous former, car l’impasse sur git n’est pas possible.
Git est la version la plus utilisée de logiciel de contrôle de version.
Qu’est-ce que le contrôle de version ? Il s’agit de stocker toutes les versions de tous les fichiers dans un projet, avec pour chaque version, des commentaires, dates et auteur.
Git est le logiciel à la mode, mais il y a eu d’autres logiciels de contrôle de version : CVS, SVN, SourceSafe, ClearCase, Mercurial, etc.
Contrairement aux logiciels précédents, qui stockaient les différences entre les versions, Git stocke les versions entières. Le dépôt Git est donc un peu plus gros. Il se trouve dans un dossier .git qui est dans le dossier racine du projet. Il ne faut jamais modifier ce dossier .git ou son contenu.
Les éléments de Git sont :
Les opérations courantes sont :
Suivent les transparents vus dans la video précédente
La boucle de travail de base est:
Commit
= créez une copie dans le dépôt GIT avec un
message de documentationEn anglais: repository.
Ce sont les données du système de contrôle de version, c’est à dire au moins toutes les versions de tous les fichiers (ou un moyen de les reconstituer). C’est aussi toutes les informations d’auteur, de temps, de dépendance, de branches…
Un dépôt GIT peut être assez gros.
Un commit
décrit une version comme un ensemble de
changements sur au moins un fichier. Un commit peut contenir beaucoup de
changements sur beaucoup de fichiers, des changements de texte, de
permission, de nom, de dossier… Un commit est identifié avec un code de
hashage (SHA-1).
Un commit a aussi un message le décrivant, et il est important de mettre un message le plus clair et simple et cohérent possible.
La copie de travail, c’est une copie de la version courante du dépôt que vous pouvez éditer et modifier. La version courante est celle marquée “HEAD”.
Vous ne pouvez pas changer la version de travail si votre copie de travail est modifiée
Si votre copie de travail est modifiée, c’est à dire différente de la version courante dans git, alors vous pouvez:
commit
stash
sauver vos changements dans la pile de stash et
revenir à la version courante dans gitSi votre copie de travail n’est pas modifiée, alors vous pouvez:
L’état de la copie de travail est affiché par
git status
Pour vous faciliter la vie, faites, dans un terminal:
git config --global core.pager ''
git config --global core.editor nano
git config --global user.name "votre nom"
git config --global user.email "votre@email"
La première ligne concerne git log
. git log
utilise par défaut un éditeur simplifié nommé “less”, et cela force à
taper q
pour sortir de l’affichage d’une liste de
commits.
La deuxième ligne concerne git commit
. Si vous
n’utilisez pas l’option -m
, alors git commit
lance l’antique éditeur de texte vi
. nano
est
un peu plus moderne et facile à utiliser.
Les deux dernières lignes simplifient les messages affichés par commit.
Cette commande crée un dépot local dans le dossier courant.
Si tout va bien, il n’y a pas de message. Tout message signale une erreur et doit être lu.
Cette commande donne des informations sur l’état du dépot git dans le dossier courant:
Cette commande permet d’ajouter un fichier ou tous les fichiers d’un dossier dans l’index.
git add src/tp01/Main.java
ajoute src/tp01/Main.java à
l’index, c’est à dire au prochain commit.
git add src
ajoute tous les fichiers dans le dossier src
à l’index.
Si tout va bien, il n’y a pas de message. Tout message signale une erreur et doit être lu.
Cette commande crée un commit à partir de tous les fichiers placés dans l’index.
git commit
crée un commit et ouvre un éditeur de texte
pour vous forcer à écrire un message de commit.
git commit -m "message"
crée un commit avec le message
donné.
Si tout va bien, il n’y a pas de message. Tout message signale une erreur et doit être lu.
Cette commande affiche des informations sur les précédents commits.
git log
affiche tous les commits
git log --stat
affiche tous les commits y compris les
informations sur les fichiers inclus dans chaque commit.
Créer un nouveau dépôt :
|
git init
git status
git add file
git add file
git log
git commit -m "message"
git status
et les fichiers du stage sont en vertSuivent les transparents de la vidéo précédente.
Pour échanger avec d’autres personnes/machines, you avez besoin d’accéder à leur dépôt et eux ont besoin d’accéder au vôtre (ou à une copie).
GIT vous permet de transférer tout ou partie d’un dépôt vers un autre dépôt.
Un dépôt Git local peut être connecté à un dépôt distant sur un serveur Git: le serveur distant a une URL d’accès.
Télécharger un logiciel libre et l’adapter:
git clone URL
pour créer un dépôt local depuis le dépôt
distant dans URLgit checkout BRANCH
pour mettre dans la copie de
travail la branche qui vous concernegit add
,
git commit
git push
pour envoyer les changements sur le dépôt
distantLa boucle de travail plus large est:
Pull
récupérez les changements du dépôt distant (par
ex: de vos collègues)commit
, etc… (c’est
la boucle initiale)Push
envoyez les nouveaux commits dans le dépôt
distantgit init
, il n’a pas de
“remote”
git remote add distant URL
git push --set-upstream distant main
git clone
, un lien vers
le dépôt distant existe avec le nom “origin”git push
envoie l’état de la branche courante vers le
premier dépôt distantgit push remoteName
envoie l’état de la branche
courante vers le dépôt distant nommé remoteNamegit fetch
est l’opposé de git push, il recopie
l’information de la branche distante dans la branche locale; la copie de
travail n’est pas modifiéegit pull
est la combinaison de git fetch
et git merge
Prenons un exemple:
public class Toto {
public Toto() {}
}
Ce fichier est dans la copie de travail chez vous et au travail.
Vous ajoutez un paramètre au constructeur chez vous :
public class Toto {
public Toto(int i) {}
}
Vous faites commit, puis push, puis vous travaillez sur autre chose pendant une semaine.
Vous êtes maintenant au travail. Vous refaites la même chose, mais un peu différemment:
public class Toto {
public Toto(int var) {}
}
Vous faites commit et push. GIT répond que votre dépôt local est en
retard sur le dépôt distant. Ce retard est du à la modification poussée
la semaine dernière. Comme le suggère GIT, vous faites
git pull
. Conflit!
Voici le contenu de votre fichier:
public class Toto {
<<<<<<< HEAD
public Toto(int var) {}
=======
public Toto(int i) {}
>>>>>>> other
}
GIT a reconnu les parties identiques, et vous montre les deux versions des parties différentes.
Pour résoudre les conflits, vous devez:
git add
et git commit
git clone URL
*.class
= ne pas suivre les fichiers avec extension
.classbin/
= ne pas suivre le dossier binfile.txt
= ne pas suivre le fichier file.txt, même si
c’est du texteCette ressource en anglais est une référence, très complète et d’accès ardu: git-scm.org
GitLab est un logiciel qui combine un serveur GIT et un serveur Web et plein d’autres outils utiles.
Le serveur GIT répond aux demandes push, pull, clone, etc…
Le serveur Web vous montre des informations sur les dépôts existants et leur contenu, vous permet de configurer votre profil et vos actions, et vous permet d’accéder à plusieurs types d’outils complémentaires :
Une première étape clef dans votre communication avec gitlab est de configurer la communication par SSH.
En général, il est possible de se connecter à gitlab/github de plusieurs façons, dont par login et mot de passe. A Télécom, seule la connexion par SSH est confortable à utiliser, mais délicate à configurer.
Je suppose que vous avez déjà une paire de clefs SSH privée et publique. Personnellement, j’ai créé une autre paire de clefs SSH spécialement pour mes communications GitLab et GitHub.
Dans votre navigateur, allez sur Gitlab. En haut à droite, cliquez sur votre compte.
Choisissez « préférences », puis « clefs SSH »
Ouvrez dans un terminal et affichez votre clef publique : recopiez la dans le presse-papiers (contrôle-C ou command-C).
Collez la clef dans la zone adéquate. Mettez un titre à votre clef, et des paramètres pertinents.
Puis « ajoutez la clef ». Voici pour la partie du gitlab.
git remote add distant URL
pour ajouter URL comme dépôt
distantgit push --set-upstream distant main
pour connecter la
branche locale main avec la branche distante main et envoyer
l’informationgit clone URL
git push
git pull
récupère ce qui a été poussé et
fait la fusion si nécessairegit commit
Clonez le dépôt: git@gitlab.enst.fr:jean-claude.dufourd/learning-merge.git
Il y a plusieurs branches à merger dans main, avec tous les cas entre merge auto, merge simple et merge qui force l’édition à la main.
Les branches sont:
Si vous executez test.py, ça doit toujours marcher. C’est donc le test pour vous assurer que les fusions se sont bien passées.
Les fusions à tester sont :
git checkout main
puis git merge pretty
:
ça devrait être automatique, le commit est souvent automatiquegit merge comment_test
: avec un outil graphique de fusion
(celui que vous préférez) choisissez les modifs à appliquer (à droite ou
à gauche), et là, il faut faire commit une fois que c’est fini.git merge refac_no_comma
: avec un outil graphique de
fusion, vous pouvez faire une partie de la fusion automatiquement, et
vous devez editer la partie centrale si vous voulez vraiment conserver
les changements des deux versions.L’opération complète est montrée dans la prochaine vidéo.
Il est important que vous vous fassiez la main en faisant, avec les outils que vous choisissez, ces fusions sur ce dépot exemple.
Merge request et pull request sont des synonymes.
Ca ne marche pas pareil selon que c’est au sein d’un même projet ou si vous proposez une correction sur un projet dont vous n’êtes pas un des gérants.
Parfois, les dépôts sont initialisés avec la branche main “protégée”.
Cela veut dire que seuls les intégrateurs, qui ont des droits
supplémentaires (maintainer
), peuvent faire commit sur la
branche main. Si c’est le cas et que vous n’êtes pas intégrateurs (juste
developer
), alors vous devez passer par une merge request
pour publier votre travail sur main. Par contre, vous pouvez commit sur
toutes les branches non protégées.
Vous êtes plusieurs à travailler sur un projet. Vous travaillez chacun sur votre branche. A la fin du projet, l’un de vous est chargé de l’intégration du projet, c’est-à-dire de vérifier que tous les bouts du logiciel développés séparément fonctionnent ensemble.
Vous avez fini votre travail sur la branche X. Il ne reste plus qu’à
fusionner la branche X avec la branche main pour intégrer votre partie.
La bonne façon de faire est de créer une merge request
.
Sur gitlab, dans votre projet, barre de gauche, “Merge Requests”, et
dans cette page, New Merge Request
La video sur le transparent suivant vous montre ce processus en pratique.
Je vous propose d’expérimenter en pratique une merge request, ou pull request. C’est une façon de dire au développeur d’un dépôt que vous avez fait une modification que vous pensez utile dans votre dépôt qui est une copie du sien, et vous lui dites où aller chercher la modification.
Faire une copie d’un dépôt s’appelle faire un fork
. Le
dépôt copie a le même nom que le dépôt de départ, donc il doit être dans
un autre espace de nom. Suite à diverses limitations, nous devons faire
cette expérimentation sur github et pas notre gitlab de Télécom.
Le scénario est :
fork
, que j’appellerai D1 et il va être à l’URL
https://github.com/votrelogingithub/ueo_mergereqvotrelogingithuborg
, ceci pour
créer un second espace de nommagefork
de votre fork
de
mon dépôt, que j’appelerai D2 et il va être à l’URL
https://github.com/orgs/votrelogingithuborg/ueo_mergereqVous allez d’abord créer une merge request :
Puis vous allez gérer la merge request :
Maintenant, vous comprenez sans doute pourquoi je vous ai fait faire 2 forks : il faut que vous ayez des droits sur D1 pour pouvoir gérer la merge request, et je ne peux pas vous donner les droits d’accès au dépôt d’origine.
Note: vous pourriez faire tout ceci avec un autre dépôt que le mien comme origine.
C’est une bonne idée de pratiquer vous-même pour faire entrer les concepts, même si c’est pour refaire exactement ce que vous avez vu dans les transparents. Ca ancre les choses dans votre mémoire, ça vous challenge si ça ne marche pas tout à fait de la même façon chez vous, ça vous force à demander de l’aide si ça ne marche pas du tout.
Tout ça, c’est bon pour vos apprentissages, même si pas forcément confortable.
https://learngitbranching.js.org/?locale=fr_FR
Faire les 4 niveaux de main (séquence d’introduction) et les 8 niveaux de remote (push et pull)
Refaites sur votre machine tous les exemples faits dans les transparents et les videos :
N’hésitez pas à demander de l’aide à vos enseignants ou à moi
Ce chapitre complète l’enseignement GIT en donnant des indices ou des corrections pour tous les problèmes entendus en séance de TP et en projet.
A priori, ce chapitre est plutôt là pour vous aider à résoudre des problèmes plus tard. Sa lecture avant d’avoir expérimenté (et fait des erreurs) avec git n’est pas utile.
smartgit est un logiciel disponible sur les plateformes habituelles et qui était utilisé dans un enseignement Java. Il y a quelques écrans de smartgit dans ces transparents, mais le même type de fonction existe dans tous les logiciels auxquels vous aurez accès: eclipse, intelliJ, visual code…
GIT gère des fichiers et leur évolution au cours du temps. Quand vous modifiez un fichier, GIT retient l’information suivante:
Tout fichier peut être mis dans GIT. Mais tous les types de fichier ne font pas sens. Par exemple, un fichier compilé à partir d’un fichier source n’a pas sa place dans GIT si le fichier source y est déjà car il peut être recréé à partir du fichier source. Donc pour vos projets Java, ne mettez pas vos fichiers .class dans GIT. Dans vos projets en C, ne mettez pas les .o dans GIT.
Pour un fichier texte, GIT va vous indiquer les différences entre deux versions, les lignes ajoutées, retirées, modifiées. Pour un fichier binaire, GIT va juste dire que le fichier a changé, et les différences n’ont pas de sens. En ce sens, il n’est pas souvent pertinent de mettre un fichier binaire dans GIT.
GIT vous permet de consigner dans un fichier la liste des fichiers
dont l’inclusion dans GIT ne fait pas sens. Ce fichier s’appelle
.gitignore
. Il peut y avoir un fichier
.gitignore
dans tous les dossiers, mais l’important est
celui du dossier principal.
Pour ignorer un fichier, mettez son nom dans une ligne du
.gitignore
. Par exemple, sous Mac, il y a un fichier qui
s’appelle .DS_Store, qui sert à Mac OSX.
Dans .gitignore, ajoutez la ligne avec .DS_Store
Pour ignorer un dossier complet, même chose, ajouter le nom du dossier suivi de /
Pour ignorer tous les fichiers .class, ajoutez une ligne avec
*.class
Un fichier ignoré n’est pas stocké dans le dépot. S’il est modifié ou
détruit, GIT l’ignore. Les fichiers ignorés ne sont donc pas présents
dans le résultat d’un git clone
.
Il est parfois difficile au début de savoir s’il faut ignorer un fichier ou pas. Je vais traiter le cas d’Eclipse, Intellij, node.js et d’Android Studio
Pour Android Studio, ne faites rien: Android Studio crée automatiquement un fichier .gitignore qui est très bien. Utilisez le tel quel.
Pour IntelliJ, il faut ignorer les dossiers .idea/
et
out/
.
Si vous utilisez node.js, alors il faut ignorer le dossier
node_modules/
.
Pour Eclipse, la question qui se pose est: dois-je mettre dans le
dépot GIT les fichiers de description du projet, à savoir le
.project
et le .classpath
. Ces deux fichiers
dépendent de la configuration de votre machine et pourront perturber vos
collaborateurs, surtout si vous avez un mélange de machines Windows, Mac
et Linux dans le projet. Ignorez ces deux fichiers.
Cela veut dire que quand vous récupérerez la première fois un dossier où il y a un projet eclipse, eclipse ne le verra pas comme un projet et il faudra que vous l’importiez par “Importer depuis des sources existants”.
Comment faire si vous avez ajouté des fichiers dans un dépot, et vous découvrez qu’il aurait fallu les ignorer.
Etape 1: ajoutez le nom des fichiers à ignorer dans .gitignore
Etape 2: faites git rm --cached
sur les fichiers
Etape 3: faites git commit
et vérifiez
Dans le screencast, je traite un exemple avec un projet eclipse dont
tout a été commit sans .gitignore
.
Voir le screencast
Avec GIT, tout tourne autour des dépots.
Un dépot est un dossier contenant un ensemble de dossiers et de fichiers qui ont une cohérence pour vous.
Faire git init
dans un dossier déclare ce dossier comme
le dossier principal de votre dépot. Il faut faire git init
dans le dossier eclipse qui contient les fichiers .project
et .classpath
, pour votre projet Java.
Il ne faut pas faire git init
dans le dossier
workspace
ou eclipse-workspace
, ni dans votre
dossier racine, ni dans le dossier src
de votre projet
Java.
Le dossier principal de votre dépot GIT contient deux choses:
.git
, souvent non visible dans
l’Explorer/Finder, qui contient les données privées du logiciel
GIT.git checkout
avec les modifications
en cours.Si vous avez le choix, vous pouvez faire autant de dépots séparés que vous voulez. Mais si le nombre de dépot est imposé, par exemple si votre entreprise doit payer le service GIT au nombre de dépots que vous créez, ou si dans PACT, nous vous donnons accès à un seul dépot pour nous faciliter le travail, alors vous pouvez facilement travailler dans un seul dépot avec plusieurs sous-projets.
Créez un dossier principal qui sera le support du dépot.
Créez un dossier par sous-projet et une branche ou plus par sous-projet.
Voilà: il n’y aura pas d’interférence entre les sous-projets si chacun travaille dans sa branche et dans son dossier.
Vous avez créé votre dépot dans le dossier du fichier
.project
, mais votre collègue a créé son dépot dans un
autre dossier, soit le dossier src, soit son dossier racine ou
workspace.
Vous avez tou.te.s les deux poussé dans un dépot distant commun, et vous découvrez le problème en essayant de faire un merge. Vous vous attendez à un merge très difficile, or il ne se passe rien. Vous retrouvez après le merge vos deux projets dans des dossiers différents
Que faire ?
Etape 1: revenir à un état avec vos fichiers dans une branche et les fichiers de l’autre dans une autre branche.
Soit vous revenez en arrière parce que cet état existe déjà dans votre dépot, car vous aviez déjà des branches séparées.
Soit vous n’aviez pas encore de branches, vous avez tout fait sous master, et il faut reconstituer deux branches séparées.
moi
et autre
à partir
de la branche master où il y a tous les fichiers.git checkout moi
moi
, détruisez tous les fichiers de
votre collègue par git rm
.git commit -a -m "message pertinent"
git checkout autre
autre
, détruisez tous vos fichiers par
git rm
.git commit -a -m "message pertinent"
Vous êtes maintenant revenu.e.s à l’état où nous pouvons faire le déplacement des fichiers dans une des deux branches.
Le but est donc de déplacer les fichiers d’une branche pour que les deux branches aient des fichiers avec les mêmes noms dans les mêmes dossiers.
Choisissez celle des deux branches dont vous voulez garder la
structure de dossier, par exemple c’est la branche moi
qui
a les bons dossiers.
Mettez vous dans la branche autre
, par
git checkout autre
. Faites git mv
sur tous les
fichiers et dossiers jusqu’à obtenir la même structure que dans la
branche moi
. Faites git commit
quand la
structure est la même.
C’est fini. Vous pouvez maintenant faire un merge pertinent entre les deux branches.
Voir le screencast
Vous voulez faire un merge avec la branche de votre binome, et git vous envoie un message contenant ‘unrelated histories’ et refuse de faire le merge.
Que se passe-t-il ?
Dans le TP, nous vous avons dit de faire comme suit:
git init
git commit
puis git push
sur le dépot distantgit clone
du dépot distantSi vous avez suivi ce processus, alors vos deux historiques GIT sont
liées par le partage du premier commit de A, récupéré par B lors du
git clone
Qu’avez-vous vraiment fait ?
git init
git commit
puis
git push
sur le dépot distantVous avez donc créé deux commits non liés entre eux et poussé deux points de départ de branche sur le dépot distant. Dans la fenetre log de smartgit, vous voyez deux lignes séparées.
Si vous n’avez pas créé de branche avant de pousser, alors le second qui a poussé a dû créer une autre branche que master pour pousser. Dans l’image, ma second branche est master2. J’ai essayé de faire un merge et le message est “refusing to merge unrelated histories”.
Vous pouvez forcer git à faire un merge. Commencez par vérifier que les structures de dossier sont les mêmes des deux cotés, et que les fichiers ont le même nom s’ils doivent être fusionnés.
Puis faites la commande:
git merge master2 --allow-unrelated-histories
Comme vous pouvez imaginer, cette option a un gros potentiel de confusion si vous l’utilisez n’importe comment. Donc faites bien les vérifications. Voici le résultat dans smargit, vue log:
Voir le screencast
Vous avez fait git init
dans un dossier puis
git init
ou git clone
dans un sous-dossier et
vous ne savez plus quoi faire.
Mettez vous dans le dossier qui est dans l’autre dossier. Faites
git status
. S’il y a des modifications, voyez si elles
doivent être sauvagardées.
Si le dossier interne contient des modifications et est un clone, alors il a un dépot distant. Commencez par déplacer le dossier interne en dehors du dossier externe. Puis les modifications peuvent être commit et push.
Si le dossier interne contient des modifications et n’a pas de dépot distant (remote), alors il faut sauver ces modifications d’une manière autre (copie du dossier, zip…).
Puis vous supprimez le dossier interne ou vous le déplacez en dehors de l’autre dossier.
Si vous aviez ajouté le dossier interne dans le GIT du dossier externe, alors il faut commit la suppression du dossier interne dans le GIT du dossier externe.
A quoi servent les branches Git ?
Que se passe-t-il sans branches ?
Avec une branche et des dossiers séparés, vous êtes complètement indépendants des autres modules, vous développez sans être perturbé.e.s par le travail des autres.
Vous pouvez même faire une branche par personne, si vous travaillez sur des parties clairement séparées de celle de votre binôme.
Quand vous êtes prêt.e.s à partager votre travail avec d’autres, vous leur dites de fusionner votre branche avec la leur. C’est le principe de la “merge request”. Les fusions dans “master” sont plutôt à faire par les intégrateurs.
Comment je peux me servir des branches Git ?
Je crée une branche à partir d’une autre
git status
)git branch toto
pour créer la branche “toto”
(je suis toujours dans la branche “tata”, “toto” et “tata” sont pour
l’instant identiques)git checkout toto
pour passer de “tata” à
“toto”git commit
, alors ils sont
ajoutés dans la branche “toto” qui change par rapport à “tata”Je fais git branch -v
pour savoir quelles sont les
branches existantes en local
Je fais git checkout tata
pour passer d’une branche à la
branche “tata”
Quand je fais git clone
, seule la branche “main” ou
“master” est importée dans le dépôt local par défaut.
git checkout tata
la première fois, git
importe tous les commits de la branche “tata” dans mon dépôt localgit fetch —all
Pour partager mon travail qui se trouve dans une branche GIT, deux possibilités
git merge source
où source est la branche
source des commits à partagergit add
sur le fichier que je viens
d’éditergit commit
quand tous les conflits sont
résolusgit rebase destination
où destination est la
branche qui va recevoir les commits partagésgit add
sur le fichier que je viens
d’éditergit commit
quand tous les conflits sont
résolusLa fusion simple est plus facile à comprendre mais crée un historique GIT plus compliqué.
Si vous avez un problème qui n’a pas de solution décrite ici, dites le à un de vos enseignants, je rajouterai une video.
Ceci est la fin de ce cours en ligne.
Tous les retours sont bienvenus par email