path = window.location.pathname.replace(".html", ".qmd");
path_modified = (path.includes('en/content')) ? path.replace('en/content', 'content/en') : path
html`${printBadges({fpath: path_modified})}`
Les exercices suivants sont inspirés d’un cours de Git que j’ai participé à construire à l’Insee et dont les ressources sont disponibles ici. L’idée du cadavre exquis est inspirée de cette ressource et de celle-ci.
Cette partie part du principe que les concepts généraux de Git
sont
maîtrisés et qu’un environnement de travail fonctionnel avec Git
est
disponible. Un exemple de tel environnement est le JupyterLab
ou l’environnement VSCode
du
SSPCloud
où une extension
Git
est pré-installée :
Outre le chapitre précédent, il existe de
nombreuses ressources sur internet sur le sujet,
notamment une série de ressources construites
pour l’Insee sur ce site
et des ressources de la documentation collaborative sur R
qu’est utilitR
(des éléments sur la configuration
et pratique sur RStudio). Toutes
les ressources ne sont donc pas du Python
car Git
est un outil transversal
qui doit servir quel que soit le langage de prédilection.
Git
fait parti des pratiques collaboratives
devenues standards dans le domaine de l’open-source
mais également de plus en plus communes dans les administrations et entreprises
de la data science.
Ce chapitre propose, pour simplifier l’apprentissage,
d’utiliser l’ extension Git
de JupyterLab
ou de VSCode
.
Un tutoriel présentant l’extension JupyterLab
est disponible
ici.
VSCode
propose
probablement, à l’heure actuelle, l’ensemble le plus complet.
Certains passages de ce TD nécessitent d’utiliser la ligne de commande.
Il est tout à fait possible de réaliser ce TD entièrement avec celle-ci.
Cependant, pour une personne débutante en Git
, l’utilisation d’une
interface graphique peut constituer un élément important pour
la compréhension et l’adoption de Git
. Une fois à l’aise avec
Git
, on peut tout à fait se passer des interfaces graphiques
pour les routines quotidiennes et ne les utiliser que
pour certaines opérations où elles s’avèrent fort pratiques
(notamment la comparaison de deux fichiers avant de devoir fusionner).
1 Configuration du compte Github
1.1 Rappels sur la notion de dépôt distant
Comme expliqué dans le chapitre précédent,
il convient de distinguer
le dépôt distant (remote) et la copie ou les copies locales (les clones)
d’un dépôt. Le dépôt distant est généralement stocké sur une forge
logicielle (Github
ou Gitlab
) et sert à centraliser la version
collective d’un projet. Les copies locales sont des copies de travail.
Git
est un système de contrôle de version asynchrone, c’est-à-dire
qu’on n’interagit pas en continu avec le dépôt distant (comme c’est le
cas dans le système SVN) mais qu’il est possible d’avoir une version
locale qui se différencie du dépôt commun et qu’on rend cohérente
de temps en temps.
Bien qu’il soit possible d’avoir une utilisation hors-ligne de Git
,
c’est-à-dire un pur contrôle de version local sans dépôt
distant, cela est une utilisation
rare et qui comporte un intérêt limité. L’intérêt de Git
est
d’offrir une manière robuste et efficace d’interagir avec un
dépôt distant facilitant ainsi la collaboration en équipe ou en
solitaire.
Pour ces exercices, il est proposé
d’utiliser Github
, la forge la plus visible.
L’avantage de Github
par rapport à son principal concurrent, Gitlab
,
est que le premier est plus visible, car
mieux indexé par Google
et concentre, en partie pour des raisons historiques, plus
de développeurs Python
et R
(ce qui est important dans des domaines comme
le code où les externalités de réseau jouent).
1.2 Première étape: créer un compte Github
Les deux premières étapes se font sur Github
.
Exercice 1 : Créer un compte Github
- Si vous n’en avez pas déjà un, créer un compte sur https://github.com
- Créer un dépôt en suivant les consignes ci-dessous.
- Créez ce dépôt privé, cela permettra dans l’exercice 2 d’activer notre jeton. Vous pourrez le rendre public après l’exercice 2, c’est comme vous le souhaitez.
- Créer ce dépôt avec un
README.md
en cliquant sur la caseAdd a README file
- Ajouter un
.gitignore
en sélectionnant le modèlePython
Connexion sur https://github.com > + (en haut de la page) > New repository > Renseigner le “Repository name” > Cocher “private” > “Create repository”
1.3 Deuxième étape: créer un token (jeton) HTTPS
1.4 Principe
Git
est un système décentralisé de contrôle de version :
les codes sont modifiés par chaque personne sur son poste de travail,
puis sont mis en conformité avec la version collective disponible
sur le dépôt distant au moment où le contributeur le décide.
Il est donc nécessaire que la forge connaisse l’identité de chacun des
contributeurs, afin de déterminer qui est l’auteur d’une modification apportée
aux codes stockés dans le dépôt distant.
Pour que Github
reconnaisse un utilisateur proposant des modifications,
il est nécessaire de s’authentifier (un dépôt distant, même public, ne peut pas être modifié par n’importe qui). L’authentification consiste ainsi à fournir un élément que seul vous et la forge êtes censés connaître : un mot de passe, une clé compliquée, un jeton d’accès…
Plus précisément, il existe deux modalités pour faire connaître son identité à Github
:
- une authentification HTTPS (décrite ici) : l’authentification se fait avec un login et un mot de passe ou avec un token (un mot de passe compliqué généré automatiquement par
Github
et connu exclusivement du détenteur du compteGithub
) ; - une authentification SSH : l’authentification se fait par une clé cryptée disponible sur le poste de travail et que
GitHub
ouGitLab
connaît. Une fois configurée, cette méthode ne nécessite plus de faire connaître son identité : l’empreinte digitale que constitue la clé suffit à reconnaître un utilisateur.
La documentation collaborative utilitR
présente les raisons pour lesquelles il convient de favoriser
la méthode HTTPS sur la méthode SSH.
Note
Depuis Août 2021, Github
n’autorise plus l’authentification par mot de passe
lorsqu’on interagit (pull
/push
) avec un dépôt distant
(raisons ici).
Il est nécessaire d’utiliser un token (jeton d’accès) qui présente l’avantage
d’être révoquable (on peut à tout moment supprimer un jeton si, par exemple,
on suspecte qu’il a été diffusé par erreur) et à droits limités
(le jeton permet certaines opérations standards mais
n’autorise pas certaines opérations déterminantes comme la suppression
d’un dépôt).
À partir de mars 2023 et jusqu’à la fin de 2023, GitHub commencera progressivement à exiger que tous les utilisateurs de GitHub activent une ou plusieurs formes d’authentification à deux facteurs (2FA). Pour plus d’informations sur le déploiement de l’inscription 2FA, consultez cet article de blog. Concrètement, cela signifie que vous devrez au choix :
- Renseigner votre numéro de portable pour valider certaines connexions grâce à un code que vous recevrez par sms ;
- Installer une application d’authentification (Ex : Microsoft Authenticator) installée sur votre téléphone qui génèrera un QR code que vous pourrez scanner depuis github, ce qui ne nécessite pas que vous ayez à fournir votre numéro de téléphone
- Utiliser une clef USB de sécurité
Pour choisir entre ces différentes options, vous pouvez vous rendre sur Settings > Password and authentication > Enable two-factor authentication.
Note
Il est important de ne jamais stocker un token, et encore moins son mot de passe, dans un projet.
Il est possible de stocker un mot de passe ou token de manière sécurisée et durable
avec le credential helper de Git
. Celui-ci est présenté par la suite.
S’il n’est pas possible d’utiliser le credential helper de Git
, un mot de passe
ou token peut être stocké de manière sécurisé dans
un système de gestion de mot de passe comme Keepass.
Ne jamais stocker un jeton Github
, ou pire un mot de passe, dans un fichier
texte non crypté. Les logiciels de gestion de mot de passe
(comme Keepass, recommandé par l’Anssi)
sont simples
d’usage et permettent de ne conserver sur l’ordinateur qu’une version
hashée du mot de passe qui ne peut être décryptée qu’avec un mot de passe
connu de vous seuls.
1.5 Créer un jeton
La documentation officielle comporte un certain nombre de captures d’écran expliquant comment procéder.
Nous allons utiliser le credential helper
associé à Git
pour stocker
ce jeton. Ce credential helper
permet de conserver de manière pérenne
un jeton (on peut aussi faire en sorte que le mot de passe soit automatiquement
supprimé de la mémoire de l’ordinateur au bout, par
exemple, d’une heure).
L’inconvénient de cette méthode est que Git
écrit en clair le jeton dans
un fichier de configuration. C’est pour cette raison qu’on utilise des jetons
puisque, si ces derniers sont révélés, on peut toujours les révoquer et éviter
les problèmes (pour ne pas stocker en clair un jeton il faudrait utiliser
une librairie supplémentaire comme libsecrets
qui est au-delà du programme
de ce cours).
Si vous désirez conserver de manière plus durable ou plus sécurisée votre jeton (en ne conservant pas le jeton en clair mais de manière hashée), est d’utiliser un gestionnaire de mot de passe comme Keepass (recommandé par l’Anssi). Néanmoins, il est recommandé de tout de même fixer une date d’expéritation aux jetons pour limiter les risques de sécurité d’un token qui fuite sans s’en rendre compte.
Exercice 2.0 : Créer un service sur le SSPCloud
En amont de l’exercice 2, pour les utilisateurs
du SSPCloud
,
il est recommandé d’ouvrir un service Jupyter
en suivant les consignes suivantes :
- Dans la page
Mes services
, cliquer sur le boutonNouveau service
; - Choisir
Jupyter-Python
; - Cliquer sur
Configuration Jupyter-Python
. ⚠️ ne pas lancer le service tout de suite ! - Faire défiler les onglets pour arriver sur l’onglet
Git
; - Remplacer la valeur sous
Cache
par un nombre important, par exemple36000
pour que le jeton que vous utiliserez soit valable 10 heures ; - Lancer le service.
Exercice 2 : Créer et stocker un token
1️⃣ Suivre la
documentation officielle en ne donnant que les droits repo
au jeton (ajouter les droits
workflow
si vous désirez que votre jeton soit utilisable pour des projets
où l’intégration continue est nécessaire).
Pour résumer les étapes devraient être les suivantes :
Settings > Developers Settings > Personal Access Token > Generate a new token > “My bash script” > Expiration “30 days” > cocher juste “repo” > Generate token > Le copier
2️⃣ Ouvrir un terminal depuis Jupyter
(par exemple File > New > Terminal
) ou VSCode
(Terminal > New Terminal
).
3️⃣ [Optionnel] Taper dans le terminal la commande
qui convient selon votre système d’exploitation pour activer le
credential helper
:
# Sous mac et linux et le datalab
git config --global credential.helper store
# Sous windows
git config --global credential.helper manager-core
4️⃣ Récupérer, sur la page d’accueil de votre dépôt, l’url du dépôt distant. Il prend la forme suivante
https://github.com/<username>/<reponame>.git
Vous pouvez utiliser l’icone à droite pour copier l’url.
5️⃣ Retournez dans le Terminal. Taper
git clone repo_url
où repo_url
est l’url du dépôt en question (vous pouvez utiliser
MAJ+Inser pour coller l’url précédemment copié)
Tapez Entrée. Dans le cas d’un répertoire privé et sans credential helper, renseignez ensuite votre identifiant, faites Entrée, puis votre personal access token, Entrée. Si vous n’avez pas d’erreur, cela signifie
que l’authentification a bien fonctionné et donc que tout va
bien. Sinon, il vous suffit de réécrire l’instruction git clone
et de retenter de taper votre personal access token. Normalement, si vous avez créé un dépôt vide dans l’exercice 1,
vous avez un message de Git
:
warning: You appear to have cloned an empty repository.
Ce n’est pas une erreur mais il est préférable de suivre la consigne de l’exercice 1 et de créer un projet non vide. Le dossier de votre projet a bien été créé.
Si vous avez une erreur, suivez la consigne présentée ci-après pour réinitialiser votre credential helper
6️⃣ Si vous le désirez, vous pouvez changer la visibilité de votre dépôt en le rendant public.
7️⃣ Stocker le token sur le SSP Cloud (ou un gestionnaire de mot de passe) :
Mon Compte -> Services externes -> Jeton d’accès personnel GitHub
Note
Si vous avez fait une faute de frappe dans le mot de passe ou dans le jeton, il est possible de vider la mémoire de la manière suivante, sous Mac ou Linux :
git config --global --unset credential.helper
Sous Windows, si vous avez utilisé l’option manager-core
évoquée ci-dessus, vous pouvez utiliser une interface graphique pour effacer le mot de passe ou jeton erroné. Pour cela, dans le menu démarrer, taper Gestionnaire d'identification
(ou Credential Manager
si Windows ne trouve pas). Dans l’interface graphique qui s’ouvre, il est possible de supprimer le mot de passe ou jeton en question. Après cela, vous devriez à nouveau avoir l’opportunité de taper un mot de passe ou jeton lors d’une authentification HTTPS.
2 Premier commit
A ce stade, nous avons configuré Git
pour être en mesure
de s’authentifier automatiquement et nous avons cloné le dépôt pour avoir une
copie locale de travail.
On n’a encore ajouté aucun fichier à Git
en supplément
de ceux créés en même temps que le dépôt. Nous allons
créer ces premiers fichiers
Exercice 3 : Indexer des modifications
- Créer un dossier 📁
scripts
depuis l’interface deJupyter
- Y créer les fichiers
script1.py
etscript2.py
, chacun contenant quelques commandesPython
de votre choix (le contenu de ces fichiers n’est pas important).
Sur la session Jupyter
d’Onyxia
, si le Clic Droit > rename
ne fonctionne pas, vous pouvez faire : File > New > Text file
après vous être assurés que vous vous situez bien dans le dossier untitled.txt
se crée. Vous pouvez le renommer,
en n’oubliant pas de changer l’extension en .py
.
- Se rendre dans l’extension
Git
deJupyter
ou deVSCode
. Vous devriez retrouver un cadre ayant cet aspect (à gauche pourJupyter
et à droite pourVSCode
).
En ligne de commande, c’est l’équivalent de
git status
- Sur
Jupyter
, en passant votre souris au dessus du nom des fichiersscript1.py
etscript2.py
, vous devriez voir un+
apparaître. Cliquez dessus. SurVSCode
, un bouton+
figure à droite du nom du fichier.script1.py
et.script2.py
.
Si vous aviez privilégié la ligne de commande, ce que vous avez fait est équivalent à :
git add scripts/script1.py
git add scripts/script2.py
Pour se remémorer ce que signifie git add
, vous pouvez vous rendre
sur ce cours dédié à Git
.
- Observer le changement de statut du fichier après avoir cliqué sur
+
. Il est désormais dans la partieStaged
En gros, vous venez de dire à Git que vous allez rendre publique une évolution du fichier, mais vous ne l’avez pas encore fait (Staged
est une liste d’attente).
Si vous étiez en ligne de commande vous auriez ce résultat après un git status
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: .gitignore
Les nouvelles modifications (en
l’occurrence la création du fichier et la validation de son contenu actuel)
ne sont pas encore archivées. Pour cela, il va falloir faire un
commit
(on rend publique une modification)
- Avant cela, regardons les modifications qu’on va prochainement
valider. Pour cela, passez la souris au dessus du nom du fichier
.gitignore
et cliquer sur le boutonDiff this file
(+ -). Une page s’ouvre et met en regard la version antérieure avec les ajouts en vert et les suppressions en rouge. Nous retrouverons cette visualisation avec l’interfaceGithub
, plus tard.
En l’occurrence, comme le fichier n’existait pas, normalement nous n’avons que des ajouts.
Il est également possible d’effectuer cela avec la ligne de commande mais c’est
beaucoup moins pratique. Pour cela, la commande à appeler est git diff
et
il est nécessaire d’utiliser l’option cached
pour lui dire d’inspecter les
fichiers pour lesquels on n’a pas encore effectué de commit
. En vert
apparaîtront les modifications et en rouge les suppressions mais, cette fois,
les résultats ne seront pas mis côte-à-côte ce qui est beaucoup moins
pratique.
git diff --cached
Il est temps de valider notre modification. Cette opération
s’appelle commit
en langage Git
et, comme son nom l’indique, il
s’agit d’une proposition de modification sur laquelle, en quelques
sortes, on s’engage.
Un commit comporte un titre et éventuellement une description. A ces
informations, Git
ajoutera automatiquement quelques éléments
supplémentaires, notamment l’auteur du commit (pour identifier la personne
ayant proposé cette modification) et l’horodatage (pour identifier le moment
où cette modification a été proposée). Ces informations permettront d’identifier
de manière unique le commit
auquel sera ajouté un identifiant aléatoire
unique (un numéro SHA) qui permettra de faire référence à celui-ci sans
ambiguïté.
Le titre est important car il s’agit, pour un humain, du point d’entrée dans l’histoire d’un dépôt (voir par exemple l’histoire du dépôt du cours. Les titres vagues (Mise à jour du fichier, Update…) sont à bannir car ils nécessiteront un effort inutile pour comprendre les fichiers modifiés.
N’oubliez pas que votre premier collaborateur est votre moi futur qui, dans quelques semaines, ne se souviendra pas en quoi consistait le commit Update du 12 janvier et en quoi il se distingue du Update du 13 mars.
Exercice 4 : Premier commit (enfin !)
Sur Jupyter
, tout se passe dans la partie inférieure de l’interface graphique.
Sur VSCode
, il faut au contraire regarder en haut.
1️⃣ Entrer le titre Initial commit
et ajouter une description
Création des premiers fichiers 🎉
.
Sur VSCode
, le titre du commit correspond à la
première ligne du message de commit, les lignes suivantes correspondent à la
description.
Le fait de nommer le premier commit “Initial commit” est une habitude, vous n’êtes pas obligé de suivre cette convention si elle ne vous plaît pas.
2️⃣ Cliquer sur Commit
. Le fichier a disparu de la liste, c’est normal,
il n’a plus de modification à valider. Pour le retrouver dans la liste
des fichiers Changed
, il faudra le modifier à nouveau
3️⃣ Sur Jupyter
, cliquer sur l’onglet History
ou sur VSCode
cliquer
sur l’icône View Git Graph
. Votre commit
apparaît à ce niveau.
Si vous cliquez dessus, vous obtenez des informations sur le commit
.
❓ Question : à ce stade, le dépôt du projet sur GitHub
(remote) a-t-il été modifié ?
Note
Si vous utilisiez la ligne de commande, la manière équivalente de faire serait
git commit -m "Initial commit" -m "Création des premiers fichiers 🎉"
L’option m
permet de créer un message, qui sera disponible à l’ensemble
des contributeurs du projet. Avec la ligne de commande, ce n’est pas toujours
très pratique. Les interfaces graphiques permettent des messages plus
développés (la bonne pratique veut qu’on écrive un message de commit comme un
mail succinct : un titre et un peu d’explications, si besoin).
3 Le fichier .gitignore
Lorsqu’on utilise Git
, il y a des fichiers qu’on ne veut pas partager
ou dont on ne veut pas suivre les modifications (typiquement les grosses bases de données).
C’est le fichier .gitignore
qui gère les fichiers exclus du contrôle de version.
Lors de la création du projet sur GitHub
, nous avons demandé la création d’un fichier .gitignore
, qui se situe à la racine du projet. Il spécifie l’ensemble des fichiers qui seront toujours exclus de l’indexation faite par Git
.
Exercice 5 : Le fichier .gitignore
1️⃣ Par défaut, le fichier .gitignore
n’est pas affiché car
les fichiers .*
sont des fichiers de configuration. Il faut activer
une option pour l’afficher. Tout en haut
de Jupyter
, cliquer sur View -> Show Hidden Files
2️⃣ Ouvrir ce fichier maintenant qu’il s’affiche et observer quelques règles écrites dedans
3️⃣ Créer un dossier data
à la racine du projet et créer à l’intérieur de celui-ci un fichier data/raw.csv
avec une ligne de données quelconque
4️⃣ Ajouter au .gitignore
le dossier data/
5️⃣ Vérifier que toutes les règles ajoutées précédemment fonctionnent comme attendu
❓ Question : que se passe-t-il lorsque l’on ajoute au .gitignore
des fichiers qui ont déjà été commit sur le projet Git ?
4 Premières interactions avec Github
depuis sa copie de travail
Jusqu’à présent, après avoir cloné le dépôt, on a travaillé uniquement
sur notre copie locale. On n’a pas cherché à interagir à nouveau
avec Github
.
Cependant, il existe bien une connexion entre notre dossier local et
le dépôt Github
. Si on utilise la ligne de commande,
on peut s’en assurer en tapant dans un terminal
git remote -v
Le dépôt distant s’appelle remote
en langage Git. L’option -v
(verbose)
permet de lister le(s) dépôt(s) distant(s). Le résultat devrait avoir la
structure suivante :
origin https://github.com/<username>/<projectname>.git (fetch)
origin https://github.com/<username>/<projectname>.git (push)
Plusieurs informations sont intéressantes dans ce résultat. D’abord on
retrouve bien l’url qu’on avait renseigné à Git
lors de l’opération
de clonage. Ensuite, on remarque un terme origin
. C’est un alias
pour l’url qui suit. Cela évite d’avoir, à chaque fois, à taper l’ensemble
de l’url, ce qui peut être pénible et source d’erreur.
fetch
et push
sont là pour nous indiquer qu’on récupère (fetch
) des modifications
d’origin
mais qu’on envoie également (push
) des modifications vers
celui-ci. Généralement, les url de ces deux dépôts sont les mêmes mais cela peut
arriver, lorsqu’on contribue à des projets opensource qu’on n’a pas créé,
qu’ils diffèrent1.
4.1 Envoyer des modifications sur le dépôt distant: push
Exercice 6 : Interagir avec Github
Il convient maintenant d’envoyer les fichiers sur le dépôt distant.
1️⃣
L’objectif est d’envoyer vos modifications vers origin
.
On va passer par la ligne de commande car les boutons push
/pull
de l’extension Jupyter
ne fonctionnent pas de manière systématique.
Taper
git push origin main
Cela signifie: “git envoie (push
) mes modifications sur la
branche main
(la branche sur laquelle on a travaillé, on reviendra
dessus) vers mon dépôt (alias
origin
)”
Remarque : Si vous obtenez l’erreur suivante error: src refspec hello does not match any
, c’est probablement que vous avez indiqué le mauvais nom de branche. La confusion se fait souvent entre le nom main
ou master
(ancienne norme de branche par défaut).
Normalement, si vous avez utilisé le credential helper
, Git
ne
vous demande pas vos identifiants de connexion. Sinon,
il faut taper
votre identifiant Github et votre mot de passe correspond au personal access token nouvellement créé !
2️⃣ Retournez voir le dépôt sur Github
, vous devriez maintenant voir le fichier
.gitignore
s’afficher en page d’accueil.
4.2 La fonctionnalité pull
La deuxième manière d’interagir avec le dépôt est de récupérer des
résultats disponibles en ligne sur sa copie de travail. On appelle
cela pull
.
Pour le moment, vous êtes tout seul sur le dépôt. Il n’y a donc pas de
partenaire pour modifier un fichier dans le dépôt distant. On va simuler ce
cas en utilisant l’interface graphique de Github
pour modifier
des fichiers. On rapatriera les résultats en local dans un deuxième temps.
Exercice 7 : Rapatrier des modifs en local
1️⃣ Se rendre sur votre dépôt depuis l’interface https://github.com
- Se placer sur le fichier
README.md
et cliquer sur le boutonEdit this file
, qui prend la forme d’un icône de crayon.
2️⃣ L’objectif est de
donner au README.md
un titre en ajoutant, au début du document, la ligne suivante :
# Mon oeuvre d'art surréaliste
Sautez une ligne et entrez le texte que vous désirez, sans ponctuation. Par exemple,
le chêne un jour dit au roseau
3️⃣ Cliquez sur l’onglet Preview
pour voir le texte mis en forme au format Markdown
4️⃣ Rédiger un titre et un message complémentaire pour faire le commit
. Conserver
l’option par défaut Commit directly to the main branch
5️⃣ Editer à nouveau le README
en cliquant sur le crayon juste au dessus
de l’affichage du contenu du README
.
Ajouter une deuxième phrase et corrigez la ponctuation de la première. Ecrire un message de commit et valider.
Le Chêne un jour dit au roseau :
Vous avez bien sujet d'accuser la Nature
6️⃣ Au dessus de l’aborescence des fichiers, vous devriez voir s’afficher le titre du dernier commit. Vous pouvez cliquer dessus pour voir la modification que vous avez faite.
7️⃣ Les résultats sont sur le dépôt distant mais ne sont pas sur votre
dossier de travail dans Jupyter
ou VSCode
. Il faut re-synchroniser votre copie locale
avec le dépôt distant :
- Sur
VSCode
, cliquez simplement sur... > Pull
à côté du bouton qui permet de visualiser le graphe Git. - Avec l’interface
Jupyter
, si cela est possible, appuyez tout simplement sur la petite flèche vers le bas, qui est celle qui a désormais la pastille orange. - Si cette flèche n’est pas disponible ou si vous travaillez dans un autre environnement, vous pouvez utiliser la ligne de commande et taper
git pull origin main
Cela signifie : “git récupère (pull
) les modifications sur la
branche main
vers mon dépôt (alias
origin
)”
8️⃣ Regarder à nouveau l’historique des commits. Cliquez sur le
dernier commit et affichez les changements sur le fichier. Vous pouvez
remarquer la finesse du contrôle de version : Git
détecte au sein de
la première ligne de votre texte que vous avez mis des majuscules
ou de la ponctuation.
L’opération pull
permet :
- A votre système local de vérifier les modifications sur le dépôt distant
que vous n’auriez pas faites (cette opération s’appelle
fetch
) - De les fusionner s’il n’y a pas de conflit de version ou si les conflits de version sont automatiquement fusionnables (deux modifications d’un fichier mais qui ne portent pas sur le même emplacement).
5 Même tout seul, ne pas se limiter à main
Au début d’une tâche particulière ou d’un projet, il est recommandé d’ouvrir des issues. Prenant la forme d’un espace de discussion, elles correpondront à la fin à des nouvelles fonctionnalités (en anglais, features). Les issues permettent également de signaler des bugs constatés, de se les répartir et d’indiquer s’ils sont réglés ou s’ils ont avancés. Une utilisation intensive des issues, avec des labels adéquats, peut
même amener à se passer d’outils de gestion de projets comme Trello
.
La branche main
est la branche principale. Elle se doit d’être “propre”. Si on veut être rigoureux, on ne pousse pas des travaux non aboutis sur main
.
Il est possible de pousser directement sur main
dans le cas de petites corrections, de modifications mineures dont vous êtes certains qu’elles vont fonctionner. Mais sachez que dans le cadre de projets sensibles, c’est strictement interdit. N’ayez pas peur de fixer comme règle l’interdiction de pousser sur main
, cela obligera l’équipe projet à travailler professionnellement.
Au moindre doute, créez une branche. Les branches sont utilisées pour des travaux significatifs :
- vous travaillez seul sur une tâche qui va vous prendre plusieurs heures ou jours de travail (vous ne devez pas pousser sur
main
des travaux non aboutis); - vous travaillez sur une fonctionnalité nouvelle et vous souhaiterez recueillir l’avis de vos collaborateurs avant de modifier
main
; - vous n’êtes pas certain de réussir vos modifications du premier coup et préférez faire des tests en parallèle.
Warning
Les branches ne sont pas personnelles : Toutes les branches sont publiées, le rebase
est interdit. Le push force est également interdit.
Il faut absolument bannir les usages de push force
qui peuvent déstabiliser les copies locales des collaborateurs. S’il est nécessaire de faire un push force
, c’est qu’il y a un problème dans la branche, à identifier et régler sans faire push force
.
Tous les merges dans main
doivent se faire par l’intermédiaire d’une pull request
dans Github
. En effet, il est très déconseillé de merger une branche dans main localement.
Exercice 8: Créer une nouvelle branche et l'intégrer dans main
1️⃣ Ouvrir une issue sur Github
. Signaler qu’il serait bien d’ajouter un emoji chat dans le README. Dans la partie de droite, cliquer sur la petite roue à côté de Label
et cliquer sur Edit Labels
. Créer un label Markdown
. Normalement, le label a été ajouté.
2️⃣ Retournez sur votre dépôt local. Vous allez créer une branche nommée
issue-1
Avec l’interface graphique de JupyterLab, cliquez sur Current Branch - Main
puis sur le bouton New Branch
. Rentrez issue-1
comme nom de branche
(la branche doit être créée depuis main
, ce qui est normalement le choix
par défaut) et cliquez sur Create Branch
.
Sur VSCode, cliquez sur ... > Branch > Create Branch
et entrez le nom issue-1
.
Si vous n’utilisez pas l’interface graphique mais la ligne de commande, la manière équivalente de faire est2
git checkout -b issue-1
3️⃣ Ouvrez README.md
et ajoutez un emoji chat (:cat:
) à la suite du titre.
Faites un commit en refaisant les étapes vues dans les exercices
précédents. N’oubliez pas, cela se fait en deux étapes:
- Ajoute les modifications à l’index en déplacant le fichier
README
dans la partieStaged
- Validation des modifications avec un
commit
Si vous passez par la ligne de commande, cela donnera :
git add .
git commit -m "ajout emoji chat"
4️⃣ Faire un deuxième commit pour ajouter un emoji koala (:koala:) puis pousser les modifications locales.
Cela peut être fait avec l’interface
de JupyterLab
grâce au bouton avec une flêche montante (il doit apparaître
en orange maintenant). Sur VSCode
, cliquez sur le bouton Publish Branch
.
Sinon, si vous utilisez la ligne de commande, vous devrez taper
git push origin issue-1
5️⃣ Dans Github
, devrait apparaître
issue-1 had recent pushes XX minutes ago
.
Cliquer sur Compare & Pull Request
. Donner un titre informatif à votre pull request
Dans le message en dessous, taper
- close #1
Le tiret est une petite astuce pour que Github
remplace le numéro de l’issue par le titre.
Cliquez sur Create Pull Request
mais
ne validez pas la fusion, on le fera dans un second temps.
Le fait d’avoir mis un message close
suivi d’un numéro d’issue #1
permettra de fermer automatiquement l’issue 1 lorsque vous ferez le merge.
En attendant, vous avez créé un lien entre l’issue et la pull request
Au passage, vous pouvez ajouter le label Markdown
sur la droite.
6️⃣ En local, retourner sur main
. Dans l’interface Jupyter
, il suffit
de cliquer sur main
dans la liste des branches. Sur VSCode
, la liste des branches
apparaît en cliquant sur le nom de la branche actuelle (issue-1
en théorie à ce stade).
Si vous êtes en ligne de commande, il faut faire
git checkout main
checkout
est une commande Git
qui permet de naviguer d’une branche à l’autre
(voire d’un commit à l’autre).
Ajouter une phrase à la suite de votre texte dans le README.md
(ne touchez pas au titre !). Vous pouvez remarquer que les emojis
ne sont pas dans le titre, c’est normal vous n’avez pas encore fusionné les versions
7️⃣ Faire un commit et un push. En ligne de commande, cela donne
git add .
git commit -m "ajoute un troisième vers"
git push origin main
8️⃣ Sur Github
, cliquer sur Insights
en haut du dépôt puis, à gauche sur Network
(cela n’est
possible que si vous avez rendu public votre dépôt).
Vous devriez voir apparaître l’arborescence de votre dépôt. On peut voir issue-1
comme une ramification et main
comme le tronc.
L’objectif est maintenant de ramener les modifications faites dans issue-1
dans la branche principale. Retournez dans l’onglet Pull Requests
. Là, changer le type de merge
pour Squash and Merge
, comme ci-dessous (petit conseil : choisissez toujours cette méthode de merge).
Une fois que cela est fait, vous pouvez retourner dans Insights
puis Network
pour vérifier que tout s’est bien passé comme prévu.
9️⃣ Supprimer la branche (branch > delete this branch). Puisqu’elle est mergée, elle ne servira plus. La conserver risque d’amener à des push
involontaires dessus.
L’option de fusion Squash and Merge permet de regrouper tous les commits d’une branche (potentiellement très nombreux) en un seul dans la branche de destination. Cela évite, sur les gros projets, des branches avec des milliers de commits.
Je recommande de toujours utiliser cette technique et non les autres.
Pour désactiver les autres techniques, vous pouvez aller dans
Settings
et dans la partie Merge button
ne conserver cochée que la
méthode Allow squash merging
6 Un cadavre exquis pour découvrir le travail collaboratif
Jusqu’à présent, nous avons découvert les vertus de Git
dans un projet
individuel. Nous allons maintenant aller plus loin dans un projet
collectif.
6.1 Le workflow adopté
Nous allons adopter le mode de travail le plus simple, le Github Flow. Il correspond à cette forme caractéristique d’arbre:
- La branche
main
constitue le tronc - Les branches partent de
main
et divergent - Lorsque les modifications aboutissent, elles sont intégrées à
main
; la branche en question disparaît :
Il existe des workflows plus complexes, notamment le Git Flow
que j’utilise
pour développer ce cours. Ce tutoriel, très bien fait,
illustre avec un graphique la complexité accrue de ce flow :
Cette fois, une branche intermédiaire, par exemple une branche development
intègre des modifications à tester avant de les intégrer dans la version
officielle (main
).
Hint
Vous pourrez trouvez des dizaines d’articles et d’ouvrages sur ce sujet dont chacun prétend avoir trouvé la meilleure organisation du travail (Git flow
, GitHub flow
, GitLab flow
…). Ne lisez pas trop ces livres et articles sinon vous serez perdus (un peu comme avec les magazines destinés aux jeunes parents…).
La méthode de travail la plus simple est le Github flow qu’on vous a proposé d’adopter. L’arborescence est reconnaissable : des branches divergent et reviennent systématiquement vers main
.
Pour des projets plus complexes dans des équipes développant des applications, on pourra utiliser d’autres méthodes de travail, notamment le Git flow
. Il n’existe pas de règles universelles pour déterminer la méthode de travail ; l’important c’est, avant tout, de se mettre d’accord sur des règles communes de travail avec votre équipe.
6.2 Méthode pour les merges
Les merges vers main
doivent impérativement passer par Github
(ou Gitlab
). Cela permet de garder une trace explicite de ceux-ci (par exemple ici), sans avoir à chercher dans l’arborescence, parfois complexe, d’un projet.
La bonne pratique veut qu’on fasse un squash commit
pour éviter une inflation du nombre de commits dans main
: les branches ont vocation à proposer une multitude de petits commits, les modifications dans main
doivent être simples à tracer d’où le fait de modifier des petits bouts de code.
Comme on l’a fait dans un exercice précédent, il est très pratique d’ajouter dans le corps du message close #xx
où xx
est le numéro d’une issue associée à la pull request
. Lorsque la pull request
sera fusionnée, l’issue sera automatiquement fermée et un lien sera créé entre l’issue
et la pull request
. Cela vous permettra de comprendre, plusieurs mois ou années plus tard comment et pourquoi telle ou telle fonctionnalité a été implémentée.
En revanche, l’intégration des dernières modifications de main
vers une branche se fait en local. Si votre branche est en conflit, le conflit doit être résolu dans la branche et pas dans main.
main
doit toujours rester propre.
6.3 Mise en pratique
Exercice 9 : Interactions avec le dépôt distant
Cet exercice se fait par groupe de trois ou quatre. Il y aura deux rôles dans ce scénario :
- Une personne aura la responsabilité d’être mainteneur
- Deux à trois personnes seront développeurs.
1️⃣ Le mainteneur crée un dépôt sur Github
. Il/Elle donne des droits au(x) développeur(s) du projet (Settings > Manage Access > Invite a collaborator
).
2️⃣ Chaque membre du projet, crée une copie locale du projet grâce à la commande git clone
ou
avec le bouton Clone a repository
de JupyterLab
.
Pour cela, récupérer l’url HTTPS du dépôt en copiant l’url du dépôt que vous pouvez trouver, par exemple, dans la page d’accueil du dépôt, en dessous de Quick setup — if you’ve done this kind of thing before
En ligne de commande, cela donnera :
git clone https://github.com/<username>/<reponame>.git
3️⃣ Chaque membre du projet crée un fichier avec son nom et son prénom, selon cette structure nom-prenom.md
en évitant les caractères spéciaux. Il écrit dedans trois phrases de son choix sans ponctuation ni majuscules (pour pouvoir effectuer une correction ultérieurement). Enfin, il commit sur le projet.
Pour rappel, en ligne de commande cela donnera les commandes suivantes à modifier
git add nom-prenom.md
git commit -m "C'est l'histoire de XXXXX"
4️⃣ Chacun essaie d’envoyer (push) ses modifications locales sur le dépôt:
git push origin main
5️⃣ A ce stade, une seule personne (la plus rapide) devrait ne pas avoir rencontré de rejet du push
. C’est normal, avant d’accepter une modification Git
vérifie en premier lieu la cohérence de la branche avec le dépôt distant. Le premier ayant fait un push
a modifié le dépôt commun ; les autres doivent intégrer ces modifications dans leur version locale (pull) avant d’avoir le droit de proposer un changement.
Pour celui/celle/ceux dont le push
a été refusé, faire
git pull origin main
pour ramener les modifications distantes en local.
6️⃣ Taper git log
et regarder la manière dont a été intégré la modification de votre camarade ayant pu faire son push
Vous remarquerez que les commits de vos camarades sont intégrés tels quels à l’histoire du dépôt.
7️⃣ Faire à nouveau
git pull origin main
Le dernier doit refaire, à nouveau, les étapes 5 à 7 (dans une équipe de quatre il faudra encore le refaire une fois).
Warning à nouveau: ne JAMAIS FAIRE
git push force
Quand on fait face à un rejet du push
, on est tenté de faire passer en force le push
malgré la mise en garde précédente.
Il faut immédiatement oublier cette solution, elle crée de nombreux problèmes et, en fait, ne résout rien. L’un des risques est de réécrire entièrement l’historique rendant les copies locales, et donc les modifications de vos collaborateurs, caduques. Cela vous vaudra, à raison, des remontrances de vos partenaires qui perdent le bénéfice de leur historique Git
qui, s’ils ont des versions sans push
depuis longtemps peuvent avoir diverger fortement du dépôt maître.
Exercice 10 : Gérer les conflits quand on travaille sur le même fichier
Dans la continuité de l’exercice précédent, chaque personne va travailler sur les fichiers des autres membres de l’équipe.
1️⃣ Les deux ou trois développeurs ajoutent la ponctuation et les majuscules du fichier du premier développeur.
2️⃣ Ils sautent une ligne et ajoutent une phrase (pas tous la même).
3️⃣ Valider les résultats (git add .
et commit
) et faire un push
4️⃣ La personne la plus rapide n’a, normalement, rencontré aucune difficulté (elle peut s’arrêter temporairement pour regarder ce qui va se passer chez les voisins). Les autres voient leur push
refusé et doivent faire un pull
.
💥 Il y a conflit, ce qui doit être signalé par un message du type :
Auto-merging XXXXXX
CONFLICT (content): Merge conflict in XXXXXX.md
Automatic merge failed; fix conflicts and then commit the result.
5️⃣ Etudier le résultat de git status
6️⃣ Si vous ouvrez les fichiers incriminés, vous devriez voir des balises du type
<<<<<<< HEAD
this is some content to mess with
content to append=======
totally different content to merge later>>>>>>> new_branch_to_merge_later
7️⃣ Corriger à la main les fichiers en choisissant, pour chaque ligne, la version qui vous convient et en retirant les balises. Valider en faisant:
git add . && git commit -m "Résolution du conflit par XXXX"
Remplacer XXXX par votre nom. La balise &&
permet d’enchaîner, en une seule ligne de code, les deux commandes.
8️⃣ Faire un push. Pour la dernière personne, refaire les opérations 4 à 8
Git
permet donc de travailler, en même temps, sur le même fichier et de limiter le nombre de gestes manuels nécessaires pour faire la fusion. Lorsqu’on travaille sur des bouts différents du même fichier, on n’a même pas besoin de faire de modification manuelle, la fusion peut être automatique.
Git
est un outil très puissant. Mais, il ne remplace pas une bonne organisation du travail. Vous l’avez vu, ce mode de travail uniquement sur main
peut être pénible. Les branches prennent tout leur sens dans ce cas.
Exercice 11 : Gestion des branches
1️⃣ Le mainteneur va contribuer directement dans main
et ne crée pas de branche. Chaque développeur crée une branche, en local nommée contrib-XXXXX
où XXXXX
est le prénom:
git checkout -b contrib-XXXXX
2️⃣ Chaque membre du groupe crée un fichier README.md
où il écrit une phrase sujet-verbe-complément. Le mainteneur est le seul à ajouter un titre dans le README (qu’il commit dans main).
3️⃣ Chacun push le produit de son subconscient sur le dépôt.
4️⃣ Les développeurs ouvrent, chacun, une pull request
sur Github
de leur branche vers main
. Ils lui donnent un titre explicite.
5️⃣ Dans la discussion de chaque pull request
, le mainteneur demande au développeur d’intégrer le titre qu’il a écrit.
6️⃣ Chaque développeur, en local, intègre cette modification en faisant
# Pour être sûr d'être sur sa propre branche
git checkout branche-XXXX
git merge main
Régler le conflit et valider (add
et commit
). Pousser le résultat. Le mainteneur choisit une des pull request
et la valide avec l’option squash commits
. Vérifier sur la page d’accueil le résultat.
7️⃣ L’auteur (si 2 développeurs) ou les deux auteurs (si 3 développeurs) de la pull request
non validée doivent à nouveau répéter l’opération 6.
8️⃣ Une fois le conflit de version réglé et poussé, le mainteneur valide la pull request
selon la même procédure que précédemment.
9️⃣ Vérifier l’arborescence du dépôt dans Insights > Network
. Votre arbre doit avoir une forme caractéristique de ce qu’on appelle le Github flow
:
Informations additionnelles
environment files have been tested on.
Latest built version: 2024-08-29
Python version used:
'3.11.6 | packaged by conda-forge | (main, Oct 3 2023, 10:40:35) [GCC 12.3.0]'
Package | Version |
---|---|
affine | 2.4.0 |
aiobotocore | 2.12.2 |
aiohttp | 3.9.3 |
aioitertools | 0.11.0 |
aiosignal | 1.3.1 |
alembic | 1.13.1 |
aniso8601 | 9.0.1 |
annotated-types | 0.7.0 |
appdirs | 1.4.4 |
archspec | 0.2.3 |
astroid | 3.1.0 |
asttokens | 2.4.1 |
attrs | 23.2.0 |
babel | 2.16.0 |
bcrypt | 4.1.2 |
beautifulsoup4 | 4.12.3 |
black | 24.8.0 |
blinker | 1.7.0 |
blis | 0.7.11 |
bokeh | 3.4.0 |
boltons | 23.1.1 |
boto3 | 1.34.51 |
botocore | 1.34.51 |
branca | 0.7.1 |
Brotli | 1.1.0 |
bs4 | 0.0.2 |
cachetools | 5.3.3 |
cartiflette | 0.0.2 |
Cartopy | 0.23.0 |
catalogue | 2.0.10 |
cattrs | 24.1.0 |
certifi | 2024.2.2 |
cffi | 1.16.0 |
charset-normalizer | 3.3.2 |
chromedriver-autoinstaller | 0.6.4 |
click | 8.1.7 |
click-plugins | 1.1.1 |
cligj | 0.7.2 |
cloudpathlib | 0.18.1 |
cloudpickle | 3.0.0 |
colorama | 0.4.6 |
comm | 0.2.2 |
commonmark | 0.9.1 |
conda | 24.3.0 |
conda-libmamba-solver | 24.1.0 |
conda-package-handling | 2.2.0 |
conda_package_streaming | 0.9.0 |
confection | 0.1.5 |
contextily | 1.6.1 |
contourpy | 1.2.1 |
cryptography | 42.0.5 |
cycler | 0.12.1 |
cymem | 2.0.8 |
cytoolz | 0.12.3 |
dask | 2024.4.1 |
dask-expr | 1.0.10 |
debugpy | 1.8.1 |
decorator | 5.1.1 |
dill | 0.3.8 |
distributed | 2024.4.1 |
distro | 1.9.0 |
docker | 7.0.0 |
duckdb | 0.10.1 |
en-core-web-sm | 3.7.1 |
entrypoints | 0.4 |
et-xmlfile | 1.1.0 |
exceptiongroup | 1.2.0 |
executing | 2.0.1 |
fastjsonschema | 2.19.1 |
fiona | 1.9.6 |
flake8 | 7.0.0 |
Flask | 3.0.2 |
folium | 0.16.0 |
fontawesomefree | 6.6.0 |
fonttools | 4.51.0 |
fr-core-news-sm | 3.7.0 |
frozenlist | 1.4.1 |
fsspec | 2023.12.2 |
funcy | 2.0 |
GDAL | 3.8.4 |
gensim | 4.3.2 |
geographiclib | 2.0 |
geopandas | 0.12.2 |
geoplot | 0.5.1 |
geopy | 2.4.1 |
gitdb | 4.0.11 |
GitPython | 3.1.43 |
google-auth | 2.29.0 |
graphene | 3.3 |
graphql-core | 3.2.3 |
graphql-relay | 3.2.0 |
graphviz | 0.20.3 |
great-tables | 0.10.0 |
greenlet | 3.0.3 |
gunicorn | 21.2.0 |
h11 | 0.14.0 |
htmltools | 0.5.3 |
hvac | 2.1.0 |
idna | 3.6 |
imageio | 2.35.1 |
importlib_metadata | 7.1.0 |
importlib_resources | 6.4.0 |
inflate64 | 1.0.0 |
ipykernel | 6.29.3 |
ipython | 8.22.2 |
ipywidgets | 8.1.2 |
isort | 5.13.2 |
itsdangerous | 2.1.2 |
jedi | 0.19.1 |
Jinja2 | 3.1.3 |
jmespath | 1.0.1 |
joblib | 1.3.2 |
jsonpatch | 1.33 |
jsonpointer | 2.4 |
jsonschema | 4.21.1 |
jsonschema-specifications | 2023.12.1 |
jupyter-cache | 1.0.0 |
jupyter_client | 8.6.1 |
jupyter_core | 5.7.2 |
jupyterlab_widgets | 3.0.10 |
kaleido | 0.2.1 |
kiwisolver | 1.4.5 |
kubernetes | 29.0.0 |
langcodes | 3.4.0 |
language_data | 1.2.0 |
lazy_loader | 0.4 |
libmambapy | 1.5.7 |
llvmlite | 0.42.0 |
locket | 1.0.0 |
lxml | 5.3.0 |
lz4 | 4.3.3 |
Mako | 1.3.2 |
mamba | 1.5.7 |
mapclassify | 2.6.1 |
marisa-trie | 1.2.0 |
Markdown | 3.6 |
markdown-it-py | 3.0.0 |
MarkupSafe | 2.1.5 |
matplotlib | 3.8.3 |
matplotlib-inline | 0.1.6 |
mccabe | 0.7.0 |
mdurl | 0.1.2 |
menuinst | 2.0.2 |
mercantile | 1.2.1 |
mizani | 0.11.4 |
mlflow | 2.11.3 |
mlflow-skinny | 2.11.3 |
msgpack | 1.0.7 |
multidict | 6.0.5 |
multivolumefile | 0.2.3 |
munkres | 1.1.4 |
murmurhash | 1.0.10 |
mypy | 1.9.0 |
mypy-extensions | 1.0.0 |
nbclient | 0.10.0 |
nbformat | 5.10.4 |
nest_asyncio | 1.6.0 |
networkx | 3.3 |
nltk | 3.8.1 |
numba | 0.59.1 |
numexpr | 2.10.1 |
numpy | 1.26.4 |
oauthlib | 3.2.2 |
opencv-python-headless | 4.9.0.80 |
openpyxl | 3.1.5 |
outcome | 1.3.0.post0 |
OWSLib | 0.28.1 |
packaging | 23.2 |
pandas | 2.2.1 |
paramiko | 3.4.0 |
parso | 0.8.4 |
partd | 1.4.1 |
pathspec | 0.12.1 |
patsy | 0.5.6 |
Pebble | 5.0.7 |
pexpect | 4.9.0 |
pickleshare | 0.7.5 |
pillow | 10.3.0 |
pip | 24.0 |
pkgutil_resolve_name | 1.3.10 |
platformdirs | 4.2.0 |
plotly | 5.19.0 |
plotnine | 0.13.6 |
pluggy | 1.4.0 |
polars | 0.20.31 |
preshed | 3.0.9 |
prometheus_client | 0.20.0 |
prometheus-flask-exporter | 0.23.0 |
prompt-toolkit | 3.0.42 |
protobuf | 4.25.3 |
psutil | 5.9.8 |
ptyprocess | 0.7.0 |
pure-eval | 0.2.2 |
py7zr | 0.20.8 |
pyarrow | 15.0.0 |
pyarrow-hotfix | 0.6 |
pyasn1 | 0.5.1 |
pyasn1-modules | 0.3.0 |
pybcj | 1.0.2 |
pycodestyle | 2.11.1 |
pycosat | 0.6.6 |
pycparser | 2.21 |
pycryptodomex | 3.20.0 |
pydantic | 2.8.2 |
pydantic_core | 2.20.1 |
pyflakes | 3.2.0 |
Pygments | 2.17.2 |
PyJWT | 2.8.0 |
pyLDAvis | 3.4.1 |
pylint | 3.1.0 |
PyNaCl | 1.5.0 |
pynsee | 0.1.8 |
pyOpenSSL | 24.0.0 |
pyparsing | 3.1.2 |
pyppmd | 1.1.0 |
pyproj | 3.6.1 |
pyshp | 2.3.1 |
PySocks | 1.7.1 |
python-dateutil | 2.9.0 |
python-dotenv | 1.0.1 |
python-magic | 0.4.27 |
pytz | 2024.1 |
pyu2f | 0.1.5 |
pywaffle | 1.1.1 |
PyYAML | 6.0.1 |
pyzmq | 25.1.2 |
pyzstd | 0.16.1 |
QtPy | 2.4.1 |
querystring-parser | 1.2.4 |
rasterio | 1.3.10 |
referencing | 0.34.0 |
regex | 2023.12.25 |
requests | 2.31.0 |
requests-cache | 1.2.1 |
requests-oauthlib | 2.0.0 |
rich | 13.8.0 |
rpds-py | 0.18.0 |
rsa | 4.9 |
Rtree | 1.2.0 |
ruamel.yaml | 0.18.6 |
ruamel.yaml.clib | 0.2.8 |
s3fs | 2023.12.2 |
s3transfer | 0.10.1 |
scikit-image | 0.24.0 |
scikit-learn | 1.4.1.post1 |
scipy | 1.13.0 |
seaborn | 0.13.2 |
selenium | 4.24.0 |
setuptools | 69.2.0 |
shapely | 2.0.3 |
shellingham | 1.5.4 |
six | 1.16.0 |
smart_open | 7.0.4 |
smmap | 5.0.0 |
sniffio | 1.3.1 |
snuggs | 1.4.7 |
sortedcontainers | 2.4.0 |
soupsieve | 2.5 |
spacy | 3.7.6 |
spacy-legacy | 3.0.12 |
spacy-loggers | 1.0.5 |
SQLAlchemy | 2.0.29 |
sqlparse | 0.4.4 |
srsly | 2.4.8 |
stack-data | 0.6.2 |
statsmodels | 0.14.1 |
tabulate | 0.9.0 |
tblib | 3.0.0 |
tenacity | 8.2.3 |
texttable | 1.7.0 |
thinc | 8.2.5 |
threadpoolctl | 3.4.0 |
tifffile | 2024.8.28 |
tomli | 2.0.1 |
tomlkit | 0.12.4 |
toolz | 0.12.1 |
topojson | 1.9 |
tornado | 6.4 |
tqdm | 4.66.2 |
traitlets | 5.14.2 |
trio | 0.26.2 |
trio-websocket | 0.11.1 |
truststore | 0.8.0 |
typer | 0.12.5 |
typing_extensions | 4.11.0 |
tzdata | 2024.1 |
Unidecode | 1.3.8 |
url-normalize | 1.4.3 |
urllib3 | 1.26.18 |
wasabi | 1.1.3 |
wcwidth | 0.2.13 |
weasel | 0.4.1 |
webdriver-manager | 4.0.2 |
websocket-client | 1.8.0 |
Werkzeug | 3.0.2 |
wheel | 0.43.0 |
widgetsnbextension | 4.0.10 |
wordcloud | 1.9.3 |
wrapt | 1.16.0 |
wsproto | 1.2.0 |
xgboost | 2.0.3 |
xlrd | 2.0.1 |
xyzservices | 2024.4.0 |
yarl | 1.9.4 |
yellowbrick | 1.5 |
zict | 3.0.0 |
zipp | 3.17.0 |
zstandard | 0.22.0 |
View file history
SHA | Date | Author | Description |
---|---|---|---|
580cba7 | 2024-08-07 18:59:35 | Lino Galiana | Multilingual version as quarto profile (#533) |
005d89b | 2023-12-20 17:23:04 | Lino Galiana | Finalise l’affichage des statistiques Git (#478) |
4c1c22d | 2023-12-10 11:50:56 | Lino Galiana | Badge en javascript plutôt (#469) |
1f23de2 | 2023-12-01 17:25:36 | Lino Galiana | Stockage des images sur S3 (#466) |
a06a268 | 2023-11-23 18:23:28 | Antoine Palazzolo | 2ème relectures chapitres ML (#457) |
56d092b | 2023-11-14 15:43:00 | Antoine Palazzolo | update readme (#451) |
09654c7 | 2023-11-14 15:16:44 | Antoine Palazzolo | Suggestions Git & Visualisation (#449) |
b6ae3e3 | 2023-11-14 05:49:42 | linogaliana | Corrige balise md |
ae5205f | 2023-11-13 20:35:43 | linogaliana | précision |
428d669 | 2023-11-13 20:31:11 | linogaliana | Exo gitignore |
66c6a29 | 2023-11-13 19:53:49 | linogaliana | jupyter sspcloud credential helper |
69d5bc7 | 2023-11-13 19:44:01 | linogaliana | mise à jour de quelques consignes |
e3f1ef1 | 2023-11-13 11:53:50 | Thomas Faria | Relecture git (#448) |
ea9400a | 2023-11-05 10:54:04 | tomseimandi | Include VSCode instructions in exogit (#447) |
9366e8d | 2023-10-09 12:06:23 | Lino Galiana | Retrait des box hugo sur l’exo git (#428) |
a771183 | 2023-10-09 11:27:45 | Antoine Palazzolo | Relecture TD2 par Antoine (#418) |
f8831e7 | 2023-10-09 10:53:34 | Lino Galiana | Relecture antuki geopandas (#429) |
5ab34aa | 2023-10-04 14:54:20 | Kim A | Relecture Kim pandas & git (#416) |
154f09e | 2023-09-26 14:59:11 | Antoine Palazzolo | Des typos corrigées par Antoine (#411) |
b649205 | 2023-08-28 15:47:09 | linogaliana | Nice image |
9a4e226 | 2023-08-28 17:11:52 | Lino Galiana | Action to check URL still exist (#399) |
3bdf3b0 | 2023-08-25 11:23:02 | Lino Galiana | Simplification de la structure 🤓 (#393) |
30823c4 | 2023-08-24 14:30:55 | Lino Galiana | Liens morts navbar (#392) |
2dbf853 | 2023-07-05 11:21:40 | Lino Galiana | Add nice featured images (#368) |
34cc32c | 2022-10-14 22:05:47 | Lino Galiana | Relecture Git (#300) |
fd439f0 | 2022-09-19 09:37:50 | avouacr | fix ssp cloud links |
3056d41 | 2022-09-02 12:19:55 | avouacr | fix all SSP Cloud launcher links |
f10815b | 2022-08-25 16:00:03 | Lino Galiana | Notebooks should now look more beautiful (#260) |
12965ba | 2022-05-25 15:53:27 | Lino Galiana | :launch: Bascule vers quarto (#226) |
9c71d6e | 2022-03-08 10:34:26 | Lino Galiana | Plus d’éléments sur S3 (#218) |
0e01c33 | 2021-11-10 12:09:22 | Lino Galiana | Relecture @antuki API+Webscraping + Git (#178) |
9a3f7ad | 2021-10-31 18:36:25 | Lino Galiana | Nettoyage partie API + Git (#170) |
2f4d390 | 2021-09-02 15:12:29 | Lino Galiana | Utilise un shortcode github (#131) |
4cdb759 | 2021-05-12 10:37:23 | Lino Galiana | :sparkles: :star2: Nouveau thème hugo :snake: :fire: (#105) |
7f9f97b | 2021-04-30 21:44:04 | Lino Galiana | 🐳 + 🐍 New workflow (docker 🐳) and new dataset for modelization (2020 🇺🇸 elections) (#99) |
36ed7b1 | 2020-10-07 12:36:03 | Lino Galiana | Cadavre exquis (#66) |
d1ad64c | 2020-10-04 14:43:55 | Lino Galiana | Finalisation de la première partie de l’exo git (#62) |
283e8e9 | 2020-10-02 18:54:30 | Lino Galiana | Première partie des exos git (#61) |
Notes de bas de page
Ce cas de figure arrive lorsqu’on contribue à des projets sur lesquels on n’a pas de droit d’écriture. Il est alors nécessaire d’effectuer un fork, une copie de ce dépôt sur laquelle on dispose de droits. Dans ce cas de figure, on rencontre généralement un nouvel alias à côté d’
origin
. nomméupstream
(cf. le tutorielGithub
pour mettre à jour un fork et qui pointe vers le dépôt source à l’origine du fork. La création du boutonFetch upstream
parGithub
facilite grandement la mise en cohérence d’upstream
etorigin
et constitue la méthode recommandée.↩︎La commande
checkout
est un couteau-suisse de la gestion de branche enGit
. Elle permet en effet de basculer d’une branche à l’autre, mais aussi d’en créer, etc.↩︎
Citation
BibTeX
@book{galiana2023,
author = {Galiana, Lino},
title = {Python pour la data science},
date = {2023},
url = {https://pythonds.linogaliana.fr/},
doi = {10.5281/zenodo.8229676},
langid = {fr}
}
Veuillez citer ce travail comme suit :
Galiana, Lino. 2023. Python pour la data science. https://doi.org/10.5281/zenodo.8229676.