Git TP
À faire à la maison
Les consignes de ce TP sont données pour une utilisation de GitHub. Il est cependant tout à fait possible de réaliser ce TP avec GitLab dont l’interface est très ressemblante.
⚠️ Il y a tout de même quelques différences :
- GitHub Repository = GitLab Projet
- Pour déclarer la clé SSH dans GitLab : cliquez sur votre avatar > Préférences > SSH keys
-
- GitHub > Sign up
- ou avec ce lien direct
Introduction
Git est un formidable outil de versionnage de fichiers qui va vous permettre de conserver efficacement l’historique de votre code aussi bien si vous travaillez seul mais également quand vous travaillez à plusieurs. Cet historique est conservé dans ce que l’on appelle un dépôt git.
Sa conception décentralisée fait qu’il est quasi impossible de perdre une donnée définitivement avec git. En particulier, la perte totale d’un ordinateur hébergeant votre code ne représentera qu’une perte minime de code si vous utilisez git correctement.
En outre, de nombreux outils de CI/CD (Continuous Intégration / Continuous Deployment) qui rendent possible l’automatisation de l’intégration et du déploiement de votre code s’appuient sur un dépôt git.
Concepts Clés
Cependant, comme tout logiciel, git demande un peu d’apprentissage, et de la pratique. Pour commencer, nous aurons besoin de certains concepts essentiels pour une utilisation efficace. Par sa conception décentralisée, un dépôt git peut exister en plusieurs endroits en même temps : sur notre machine, sur chaque machine des membre du projet, ou sur un serveur hébergeant le projet.
Nous parlerons de la copie distante (remote en anglais) du dépôt dans le cas du serveur distant. En général, une seule copie distante est utilisée, mais par sa nature décentralisée, plusieurs copies distantes sont possibles (possibilité non incluse dans ce TP).
La copie sur notre machine est la copie locale (local en anglais). Il s’agit de toutes les informations du dépôt concernant l’historique de ses fichiers, et les métadonnées du dépôt. Une distinction subtile est alors faite entre la copie locale et la copie de travail (working copy en anglais) : Nos modifications sur les fichiers du dépôt n’intégrerons la copie locale qu’à notre demande explicite. Cette intégration sera alors effectuée par l’ajout d’une entrée à l’historique du dépôt.
Programme
Pour utiliser git, donc pour gérer un dépôt, nous avons accès à de nombreuses commandes. Pour ce TP de découverte vous allez utiliser seulement les commandes suivantes :
Commande | Description |
---|---|
git clone <adr> |
Créer un dépôt local sur son poste |
git status |
Voir où l’on en est |
git add <file> |
Ajouter pour le prochain commit |
git commit -m "<msg>" |
Créer un point de sauvegarde |
git pull |
dépôt local ➡️ dépôt distant |
git push |
dépôt local ⬅️ dépôt distant |
1 Git Bash et Unix
Avant de nous lancer avec git, prenons quelques minutes pour découvrir le terminal Git Bash et les principales commandes Unix.
Ces commandes ne sont pas indispensables pour utiliser git, mais il est utile et préférable de les connaitre.
-
- cela ouvre un terminal
Pour vous aider, voici la liste des commandes.
1.1 Création d’une arborescence
pwd
cd /p
ll
mkdir Cours1A
cd Cours1A
mkdir git-initiation
cd git-initiation
Il était également possible de tout faire d’une seule traite :
mkdir -p /p/Cours1A/git-initiation && cd $_
- l’option -p de mkdir crée tous les dossiers et sous-dossiers s’ils n’existent pas déjà
- $_ : correspond au dernier argument de la commande précédente
1.2 Les fichiers
-
- ps liste tous les processus en cours
ps > a.txt
-
cat b.txt | grep ps
- Les flèches ⬆️ et ⬇️ pour naviguer dans l’historique des dernières commandes et éviter de retaper 10 fois la même commande
- TAB pour l’autocomplétion
- Tapez
cat b
, puis appuyez sur la touche TAB - Il n’y a qu’un seul fichier commençant par b donc l’autocomplétion s’effectue
- La touche TAB se situe à gauche du clavier dessous
²
et dessus 🔒
- Tapez
Pour aller plus loin, vous pouvez consulter le chapitre Linux 101 du cours de Mise en production de l’ENSAE.
2 Paramétrage de Git
2.1 Configuration
-
setup-git.sh
git config --global user.name "Prenom Nom" git config --global user.email prenom.nom@eleve.ensai.fr git config --global credential.helper store git config --global core.mergeoptions --no-edit git config --global core.editor "code -w"
2.2 Création d’une clé SSH
Pour permettre de faire dialoguer notre dépôt local avec le dépôt distant de GitHub, vous utiliserez le protocole SSH
. Pour cela, vous allez :
- générer une paire de clés (publique/privée) sur notre machine
- déclarer votre clé publique à GitHub
Ce paramètrage SSH est réalisé au niveau de la machine.
Si par exemple, vous souhaitez utiliser Git sur votre ordinateur personnel, il faudra faire également ce paramétrage.
Dans Git Bash :
-
mkdir -p ~/.ssh
-
ssh-keygen -t rsa -b 4096 -N '' -q -f ~/.ssh/id_rsa
-
cat ~/.ssh/id_rsa.pub | clip
- c’est comme si vous copiez le contenu du fichier id_rsa.pub
Déclarez votre clé publique à GitHub, pour pouvoir ensuite faire communiquer dépôts locaux avec les dépôts distants :
-
- Title : VM ENSAI
- Key : Collez votre clé publique
SSH (Secure Shell) est un protocole permettant de se connecter à un autre ordinateur sur un réseau de manière sécurisée.
SSH chiffre toutes les informations échangées afin de protéger les données.
SSH utilise un mécanisme de clés cryptographiques pour authentifier les ordinateurs et les utilisateurs, garantissant que la connexion est effectuée avec le bon serveur et sans intervention malveillante :
Clé privée
: C’est comme la clé de votre maison. Vous la gardez en sécurité avec vous et ne la partagez avec personne. Cette clé reste sur votre ordinateur et sert à prouver votre identité.Clé publique
: Elle serait comme votre adresse postale. Vous pouvez la partager avec d’autres. Dans SSH, vous placez votre clé publique sur les serveurs ou les ordinateurs auxquels vous souhaitez vous connecter.
Ces deux clés sont liées. Un message chiffré par la clé publique n’est déchiffrable que par celui qui posséde la clé privée. Lorsque vous chiffrez un message avec votre clé privée, vous prouvez à tous votre identité car chacun peut déchiffrer ce message avec la clé publique.
2.3 Le terminal Git Bash
- Créez un dossier depot1 et entrez dans ce dossier
- Afficher le chemin du répertoire courant avec la commande
pwd
: print working directory
3 Créez un dépôt distant
-
- GitHub > Repositories >
- Repository name : tp-git
- Visibility Level : Private
- Cochez Add a README file
- Add .gitignore : Python
- Choose a license : MIT Licence
- Cliquez sur
Dans le cadre de ce TP, il est interdit d’éditer des fichiers directement sur GitHub. Ce n’est pas une bonne pratique.
Toutes les modifications doivent être faites sur votre clone local et ensuite envoyées vers GitHub.
4 Créez un dépôt local
Suite à la création de votre compte GitHub, vous avez créé un Repository (i.e. un dépôt distant).
Vous allez maintenant créer une copie locale de ce dépôt en clonant ce projet.
Sur la page GitHub de votre repo :
Dans Git Bash :
-
cd /p/Cours1A/git-initiation/depot1
-
git clone <collez l'adresse ssh>
- exemple : git clone git@github.com:ludo2ne/tp-git.git
Lors du clonage, vous allez peut-être avoir la question suivante :
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Écrivez yes
puis ENTREE.
-
- Le dossier tp-git est apparu ➡️ c’est votre clone local
- vous pouvez également vérifier sa présence via l’explorateur Windows
- WIN + E, puis allez à P:1A-initiation
-
- à la fin de votre prompt, vous remarquerez l’apparition de (main)
- cela signifie que vous êtes dans un dépôt git, sur la branche principale
Vous pouvez fermer Git Bash.
Vous allez par la suite utiliser le Git Bash (exactement le même) qui est intégré dans l’IDE Visual Studio Code. Vous allez utiliser ce logiciel pour la majorité des cours d’informatique de l’ENSAI.
Un IDE (Integrated Development Environment) est une application qui offre des outils complets pour le développement logiciel.
Les composants principaux d’un IDE :
- Éditeur de Code
- Compilateur / Interpréteur
- Gestionnaire de Projet
- Terminal Intégré
5 Visual Studio Code - Config
Commençons par déclarer Git Bash comme le terminal par défaut. C’est plus pratique et convivial lorsque l’on utilise git.
6 Votre dépôt local dans VSCode
Vous allez maintenant ouvrir votre dépôt local avec Visual Studio Code :
-
- Allez dans P:/Cours1A/git-initiation/depot1
- Cliquez une seule fois sur le dossier tp-git
- Puis sur le bouton
- Yes I trust the authors
- ⚠️ dans votre explorer en haut à gauche, le dossier parent doit être tp-git
- si ce n’est pas le cas, recommencez l’Open Folder
-
- Terminal > New Terminal (raccourci : CTRL + ù)
7 Premiers pas avec Git
Vous allez commencer par créer de nouveaux dossiers et fichiers sur votre dépôt local.
-
- dans VSCode > clic droit dans l’Explorer > New Folder
- ce dossier contiendra vos programmes
-
- 💡 racine du dépôt = dossier tp-git
-
- dans le dossier src
- ouvrez ce fichier et collez ce code
voiture.py
class Voiture: """Classe représentant une voiture. Attributes ---------- nom : str le nom de la voiture. couleur : str la couleur de la voiture. vitesse : int la vitesse de la voiture (initalisée à 0). """ def __init__(self, nom, couleur): """Constructeur""" self.nom = nom self.couleur = couleur self.vitesse = 0 def __str__(self): return f"La voiture {self.nom} de couleur {self.couleur} roule à {self.vitesse} km/h."
7.1 Add, Commit, Pull et Push
C’est l’enchainement de commandes qu’il faut connaitre ! (avec une pincée de status si besoin)
Avant de commencer, vérifiez dans votre terminal que vous êtes bien positionné à la racine de votre dépôt. C’est à dire que le texte jaune de votre prompt est : /p/Cours1A/git-initiation/depot1/tp-git
Dans le terminal Git Bash intégré dans VScode, exécutez les commandes suivantes :
-
- différences entre la version de travail du code et le commit le plus récent
- le dossier
src
apparait dans Untracked files - cela signifie que Git a repéré ce dossier mais qu’il ne le versionnera pas
-
- pour faire reconnaitre ce dossier et le placer la zone de transit
- ce dossier et ses fichiers seront versionnés dans le prochain commit
-
- maintenant le fichier est reconnu par Git
-
- permet de faire un commit = un point de sauvegarde pour git = une entrée supplémentaire à l’historique
- entre les
" "
, mettez un message court et explicite. Ce message est obligatoire !
-
- Your branch is ahead of ‘origin/main’ by 1 commit
- votre dépôt local est en avance d’un commit par rapport au dépôt distant
-
- récupére les derniers commits disponibles sur le dépôt distant (sur GitHub)
- actuellement il n’y en a pas, mas il faut prendre l’habitude de souvent récupérer les derniers commits
-
- pousse vos commits vers le dépôt distant.
- ⚠️ si vous avez modifié des fichiers qui ne sont pas dans un commit, ces modifications n’apparaitront pas sur le dépôt distant
Allez sur la page GitHub de votre repo et vérifiez que vos fichiers sont bien arrivés.
Vous avez tout bien fait mais votre fichier voiture.py n’est pas à jour sur GitHub. 😕
La cause dans 95 % des cas est que votre fichier voiture.py n’a pas été enregistré.
Solution : enregistrez le fichier et recommencez (Add, Commit, Pull et Push). 😩
Retournez sur VSCode :
-
voiture.py
def accelere(self, increment) -> None: """Augmente la vitesse de la voiture. L'incrément maximal est de 10 km/h. La Vitesse maximale est de 130 km/h. Parameters ---------- increment : int la valeur de l'accélération demandée (limité à 10) """ if increment > 10: = 10 increment self.vitesse = min(130, self.vitesse + increment)
Dans le terminal Git Bash
-
- le fichier voiture.py a été modifié
-
- q pour quitter
7.2 Historique du dépôt
-
- en cliquant sur Commit (en dessous du bouton )
- historique d’un fichier en ouvrant ce fichier et en cliquant sur History
-
- ce n’est pas aisément lisible
- heureusement il est possible d’améliorer cette commande
git log --pretty=format:'%C(yellow)%h %C(green)%ad %C(blue)%an%C(green)%d %Creset%s' --date=relative
- chaque ligne représente un commit
- la première colonne correspond au numéro court de commit
- vous remarquez un décalage entre HEAD et origin/HEAD (entre dépôt local et distant)
- HEAD : pointeur qui représente la version actuelle du code dans votre espace de travail
- main (ou master) : nom de la branche principale par défaut
- origin : désigne le dépôt distant
- q pour quitter
Ce n’est pas évident de se souvenir de commandes aussi longues.
Une solution est de créer un alias :
-
git config --global alias.blog "log --pretty=format:'%C(yellow)%h %C(green)%ad %C(blue)%an%C(green)%d %Creset%s' --date=relative"
-
- les 2 dépôts sont de nouveau synchronisés
Pour résumer voilà ce que vous avez fait :
7.3 Exercice d’application
-
fibonacci.py
def fibonacci(n): """Calcule le n ième terme de la suite de Fibonacci en utilisant un algorithme récursif. """ if n < 2: return 1 else : return fibonacci(n - 1) + fibonacci(n - 2) if __name__ == "__main__": for i in range (1, 15): print(fibonacci(i))
-
puissance_rec.py
def puissance_rec(nombre, puissance): if not puissance: return 1 elif not puissance % 2: return puissance_rec(nombre, int(puissance / 2)) \ * puissance_rec(nombre, int(puissance / 2)) else: return nombre * puissance_rec(nombre, puissance - 1)
7.4 Le fichier .gitignore
Grâce à ce fichier, vous pouvez dire à Git d’ignorer certains fichiers.
-
joueuses.csv
id_joueuse,nom,prenom,date_naissance,pays 1,Sebag,Marie,1986-10-15,France 2,Polgar,Judit,1976-07-23,Hongrie 3,Hou,Yifan,1994-02-27,Chine 4,Kosteniuk,Alexandra,1984-04-23,Suisse 5,Ju,Wenjun,1991-01-31,Chine
-
- le dossier data apparait dans les Untracked files
-
- le dossier data n’apparait plus car maintenant Git ignore ce dossier et son contenu
- il est bien présent dans votre dépôt local mais il n’arrivera donc jamais sur le dépôt distant
Certains fichiers ont vocation à rester seulement sur votre dépôt local, par exemple :
- fichiers de données
- fichiers contenant des mots de passe
- fichiers de logs
8 Simulation de travail en groupe
Pour les questions suivantes, vous allez avoir besoin de 2 dépôts locaux et d’un dépôt distant. Il y a 2 possibilités :
- soit vous travaillez en bînome (vous avez chacun votre dépôt local)
- soit vous faîtes seul (mais vous gérez 2 dépôts locaux différents)
Un des 2 membres va créer un dépôt local à partir du dépôt distant de l’autre.
-
- page GitHub du repo > Settings > Collaborators
-
- explorateur Windows > aller dans P:/Cours1A/git-initiation/
- créez un dossier
depot2
, et entrez dans ce dossier - clic droit > Open Git Bash here
git clone <adresse_ssh_depot_distant_de_frog>
Dans l’explorateur Windows :
-
git clone xxx
comme fait précédemment
- Vous avez donc 2 dépôts locaux distincts
- P:/Cours1A/git-initiation/tp-git 🐸
- P:/Cours1A/git-initiation/depot2/tp-git 🐱
- ils sont indépendants mais tous deux reliés au même dépôt distant
-
- File > Open Folder > P:/Cours1A/git-initiation/depot2/tp-git
-
moto.py
class Moto: def __init__(self, nom, couleur): self.couleur = couleur self.nom = nom self.vitesse = 0 def accelere(self, increment): if increment > 15: = 15 increment self.vitesse = min(150, self.vitesse + increment)
-
- il récupére le fichier moto.py dans son dépôt local
-
- 🐱 crée un fichier
velo.py
et le pousse - 🐸 le récupère
- 🐱 crée un fichier
Nous allons maintenant illustrer le fait que votre dépôt local doit être impérativement à jour pour pousser du code.
Vous allez faire en parallèle (1, 2, 3, partez) :
-
state-diag.md
```mermaid stateDiagram login : Se connecter menu_joueur : Menu Joueur logon : Créer un compte [*] --> Accueil Accueil --> login login --> menu_joueur Accueil --> logon Accueil --> quitter quitter --> [*] ```
-
git add .
git commit -m "<complétez>"
git push
Pour 🐸 qui a poussé son code en premier ➡️ tout s’est bien passé
Pour 🐱, il a du recevoir ce genre de message
! [rejected] main -> dev (fetch first) error: failed to push some refs to 'git@github.com:ludo2ne/tp-git.git' hint: Updates were rejected because the remote contains work that you do hint: not have locally. This is usually caused by another repository pushing hint: to the same ref. You may want to first integrate the remote changes hint: (e.g., 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details.
-
- si vous lisez le message, c’est assez clair
- votre dépôt local est en retard de version par rapport au dépôt distant qui fait foi
- vous devez donc mettre à jour votre dépôt local avant de pousser
-
- il fait donc un pull
8.1 Exercice d’application
8.2 Un premier conflit
Pour le moment vous avez travaillé sur des fichiers différents, donc git arrive à gérer la situation.
Maintenant, que se passe-t-il si vous modifiez tous les deux le même fichier ?
Vous allez tous les 2 travailler sur le fichier voiture.py
. Dans la méthode accelere() :
-
- si vous avez bien compris, vous savez que le push ne va pas fonctionner
-
- Et là c’est le conflit…
remote: Enumerating objects: 7, done. remote: Counting objects: 100% (7/7), done. remote: Compressing objects: 100% (3/3), done. remote: Total 4 (delta 2), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (4/4), 1015 bytes | 8.00 KiB/s, done. From github.com:ludo2ne/tp-git c27c708..05380ea main -> origin/main Auto-merging src/voiture.py CONFLICT (content): Merge conflict in src/voiture.py Automatic merge failed; fix conflicts and then commit the result.
- Git vous prévient qu’il n’est pas arrivé à fusionner les commits automatiquement
- Un conflit est généré quand les mêmes lignes d’un fichier sont modifiés par 2 commits de manière différente
Votre code ressemble à cela désormais à :
def accelere(self, increment) -> None:
if increment > 10:
= 10
increment <<<<<<< HEAD
self.vitesse = min(110, self.vitesse + increment)
=======
self.vitesse = min(150, self.vitesse + increment)
>>>>>>> 05380ea70dbd5d4e49371af8da7c0ac1df13a010
- La première partie (entre
<<<<<<< HEAD
et=======
) correspond au code en que vous aviez dans votre copie de travail - La seconde partie est le code provenant du dépôt distant
- Plusieurs choix s’offrent à vous :
- Imposer votre version (110)
- Accepter la version de 🐱 (150)
- Choisir une toute autre version (par exemple 120)
Résolvons ce conflit
-
- et supprime toutes les autres lignes de
<<<<<<<
à>>>>>>>
- autre possibilité offerte par VSCode, cliquer sur Accept Current Change
- et supprime toutes les autres lignes de
-
- vous remarquerez qu’avant le commit, le prompt affichait (main|MERGING)
- ce qui signifie que vous êtes en train de fusionner du code
Avoir un conflit, ce n’est pas grave !
Avoir un conflit, ce n’est pas grave !
Avoir un conflit, ce n’est pas grave !
Avoir un conflit, ce n’est pas grave !
Avoir un conflit, ce n’est pas grave !
Conflit ≠ Erreur
Cela arrive simplement quand Git rencontre 2 versions et il n’a pas de 🔮, ni de 🎲 pour choisir laquelle est la bonne.
- Essayez de ne pas coder en même temps sur les mêmes fichiers
- Faites des pull et push réguliers
Plus le code de votre dépôt local sera “proche” de celui du dépôt distant, moins vous en aurez.
En effet, si vous codez pendant 5 jours sans jamais pousser votre code, vous prenez le risque que d’autres personnes modifient les mêmes fichiers et poussent avant leur code.
8.3 Exercice d’application
Dans le constructeur de la classe Voiture :
-
voiture.py
def __init__(self, nom, couleur, vitesse_max=130): """Constructeur""" self.nom = nom self.couleur = couleur self.vitesse = 0 self.vitesse_max = vitesse_max
-
voiture.py
def __init__(self, nom, couleur, carburant): """Constructeur""" self.nom = nom self.couleur = couleur self.vitesse = 0 self.carburant = carburant