7  Clonage, pull, push et branches

7.1 Création d’un dépôt git et son clonage

Une fois la connection entre RStudio et une plateforme établie:

  • Les opérations se feront toujours dans un projet.
  • La méthode la plus employées est la création du dépôt à distance, il est toutefois possible de tout réaliser via R (package usethis) si on est sur la plateforme Github

7.1.1 Création d’un dépôt distant

  • Se mettre sur homepage si nécessaire en cliquant sur l’icone gitlab (en haut à gauche)
  • Cliquer sur New Project
    • Create blank project [pour ce chapitre]
    • Create from template [pour le chapitre suivant]

7.1.1.1 Création d’un dépôt sans utiliser de template

  • Par défaut: le dépôt est en mode private. Il n’est visible que par les personnes collaborant au projet.
    • Saisir un nom de dépôt.
    • Option de l’url:
      • On peut choisir son nom d’avatar après https://gitlab.com/
      • Par défaut le dossier final est le nom du dépôt saisi. On peut le changer.
    • Private/Public:
      • Par défaut private. On peut le passer en mode public.
      • On pourra changer ce mode dans les paramètres du projet [voir plus loin].
    • Garder la création d’un fichier README.md.

7.1.1.2 Changer la visibilité et supprimer un projet

  • Aller dans la barre verticale à gauche: Setting General

  • Visibilité: Passer de public à private et inversement:

    • Cliquer sur expand Visibility, project features, permissions Project visibility .
  • Supprimer un dépôt: Tout en bas de la page aller sur Advanced.

Fichier .gitignore

Ce fichier est important. A la création du dépôt distant, il n’est pas généré. Pas de soucis, avec Rstudio il sera automatiquement ajouté à votre répertoire local lors de la création du projet, avec déjà certains fichiers exclus des transferts (.Rproj.user, .Rhistory, .RData, .Ruserdata).

  • Sur la page du profil, aller sur Repositories et cliquer sur New.
  • Donner un nom au répertoire.
  • Sélectionner le type de visibilité (par défaut Public). On pourra changer à souhait de visibilité dans les paramètres du dépôt (Settings).
  • Sélectionner l’ajout un fichier README.md.
  • Vous pouvez ajouter un fichier .gitignore (dont un avec un template R), mais celui ci sera généré automatiquement avec la création du projet sous RStudio.

7.2 Clonage d’un dépôt distant dans RStudio

  • Les manipulations sont strictement identiques avec Gitlab et Github.
  • Le clonage du répertoire distant dans Rstudio se fera ici via protocole HTTPS.

Les étapes:

7.2.1 Dans le répertoire distant

  • Dans le dépôt cliquer sur l’icône Code
  • Copier le lien du dépôt (ici via https).

7.2.2 En local dans RStudio

  • Créer un nouveau projet: File New project

  • Sélectionner Version control

  • Git

  • Coller le lien récupéré dans le dépôt

  • Sélectionner un répertoire pour le projet

  • Créer le projet

 

 

 

 

Lorsque le projet a été créé après clonage du dépôt distant:

Un onglet Git apparait dans l’environnement:

  • Un menu permet d’effectuer directement des opérations de versionnage et de transferts de fichiers.

  • Des fichiers sont affichés:

    • Les fichiers générés à la création du projet comme .gitignore et ici test_support.Rproj. Ce sont donc des nouveaux éléments par rapport au dépot distant.
  • Des fichiers ne sont pas affichés:

    • Le fichier README.md généré lors de la création du dépôt distant puis cloné sur le répertoire local.
    • Les fichiers renseignés automatiquement dans le fichier .gitignore: .Rproj.user, .Rhistory, .RData, .Ruserdata.
  • On peut toujours visualiser l’ensemble des fichiers du projet sont dans la fenêtre Files.

  • Dans le terminal (bash):

    • Le répertoire est calé sur la racine du projet.
    • La branche de destination est indiquée entre parenthèses, main ou (master).

A ce stade, on peut déjà mettre à jour le répertoire distant avec les éléments générés lors de la création du projet.

Générer un projet et créé un dépot sur Github à partir de R avec le package usethis

A faire peut être sous forme de fiche pour ne pas alourdir ce support. Avec trois fonctions du package usethis, on peut générer relativement rapidement un dépôt github associé à un projet tout en restant sur la console R.

Rapidement les différentes étapes:

  • Installation et chargement du package usethis.
  • Création d’un projet R: fonction create_project().
  • Création d’une instance git dans le projet: use_git().
  • Création d’un dépôt distant sur github: use_github().

Prévoir la création de deux sessions RStudio lors de ces étapes.

7.3 Les principales opérations git pour transférer des fichiers

Important

Encore une fois, on reste ici sur un objectif de déploiement d’une documentation. Les commandes git status, git add ou git commit sont avant tout des opérations permettant d’effectuer le versionnage du projet: la première pour vérifier le statut des fichiers (modification, création, suppression), la seconde pour sélectionner des fichiers à versionner, et la troisième pour figer un état du projet.

Pour des raisons pédagogiques on privilégiera dans un premier temps l’exécution par clic bouton dans la fenêtre git de Rstudio. Néanmoins, on peut conseiller de passer directement par les commandes, par défaut très simple, via le terminal.

7.3.1 Statut et séléction des fichiers

Dans l’onglet Git on peut sélectionner les fichiers qui vont être transférés sur le dépôt distant en les cochant (colonne Staged). Leur statut passe de ? (jaune) à A (Added).

Remarque: le statut des fichiers peut être visualisé dans le terminal avec la commande git status. Cette commande ne réalise aucune opération.

S’il y a beaucoup de fichiers1, il est préférable de passer directement par la ligne de commande dans le terminal, surtout si on souhaite sélectionner l’ensemble.

Dans le terminal, pour sélectionner et ajouter un ou plusieurs fichiers au versionnage:

Ajout d'un fichier
git add nom_fichier
Ajout de tous les éléments modifiés
git add .

7.3.2 Fixer un état de la chronologie du projet: commit

  • Dans l’onglet GIT: cliquer sur Commit .
    • On remarque que le contenu texte des fichiers est affiché. Ici tout est en fond vert car ce sont des nouveaux fichiers et non des modifications de fichiers existants.
    • On doit obligatoire renseigner l’objet de ce commit dans la fenêtre Commit message: par exemple ici “First add”. On valide avec bouton Commit.

 

 

  • Commande du terminal:
Syntaxe de la commande commit
git commit -m "message/titre"

7.3.3 Transférer les fichiers du local au distant: push

Pour effectuer ce transfert on fait un PUSH.

Fèche montante dans la fenêtre git ou dans la fenêtre commit.

 

Dans le terminal:

Transférer les fichiers
git push

En résumé le transfert peut être effectué rapidement dans le terminal avec 3 commandes, git status n’ayant qu’une visée informative. Si on sélectionne tous les fichiers modifié depuis le précédents commit:

git add .
git commit --m "objet/titre"
git push

Sur le répertoire distant, ici sur Gitlab, les deux fichiers ont bien été ajoutés.

7.3.4 Du distant au local: pull

Hors travail via des branches secondaires qui seront fusionnées avec la branche principale, il n’est pas conseillé de modifier directement les fichiers du projet dans répertoire distant. Si c’est le cas2, il ne sera pas possible de faire remonter directement avec un PUSH le local vers le distant. Il faudra au préalable une synchronisation descendante du distant vers le local. Cette opération est réalisée avec un PULL.

Avertissement

S’il n’est pas conseillé d’éditer un fichier manuellement sur le distant, ça l’est est encore moins de modifier sans synchronisation préalable un même fichier sur le local et le distant à partir d’une même version du projet. Sinon cela sera un passage assuré vers la case CONFLICT… et il faudra choisir entre les deux versions modifiées.

Exemple en modifiant le fichier README.md dans le dépôt distant (gitlab).

  • Dans le dépôt distant, aller sur le fichier README.md
  • Cliquer sur le bouton edit
  • Sur Gitlab préférer l’option Edit a single file
  • On versionne avec le bouton Commit change en bas (ici Update Readme.md, mais on peut changer le titre du commit).

De retour sur le répertoire local, si on veut PUSHER des modifications locales (hors fichier Readme.md), l’opération sera rejetée. Il faut donc que les modifications apportées aux dépôt distant soient récupérées en local.

Par exemple ici, on a ajouté un nouveau fichier: ProgrammeR.R. La fenêtre indique que le push a été rejeté:

Pour effectuer cette récupération des éléments modifiés directement dans le dépôt distant et mettre les deux répertoire sur un même niveau, il faut effectuer un PULL:

  • Via l’onglet Git + cliquer sur PULL.
  • Via la fenêtre commit + cliquer sur PULL.
  • Via le terminal utiliser la commande git pull.

Une fois cette opération réalisée, le nouveau programme pourra êtré déposé sur le dépôt distant.

Avec les commandes:

récupération des modifications dans le dépôt distant
git pull
Ajout d'un fichier dans le dépôt distant 
git add .
git commit --m "Add ProgrammeR.R"
git push
Important

L’opération PULL ne supprimera pas le fichier ProgrammeR.R créé dans le répertoire local et absent du dépôt distant. Il n’existe pas en distant, donc pas de delta sur ce niveau. La mise à jour ne concernera que la modification du fichier README.md.
Par contre, si on supprime un fichier sur le dépôt distant et qu’il est présent sur le répertoire local, il sera supprimé du local lors du PULL. En cas de regret pas de panique, la suppression aura fait l’objet d’un commit et on pourra donc toujours récupérer cet éléments supprimé.

Si en local on avait modifié le fichier Readme, à une virgule ou à un espace près, lui même modifié préalablement sur le dépôt distant….CONFLICT. Et c’est justement ce qu’on va faire dans la section suivante.

7.4 Les conflits

On va générer un conflit très simple sur un fichier readme.md en l’éditant dans un premier temps sur le dépôt distant puis sur le répertoire local, sans avoir effectué un pull.

  • Edition sur le dépot distant avec le texte “Modification du readme dans gitlab
    • Application d’un commit
  • Edition sur le répertoire local avec le texte “Modification du readme dans RStudio
    • Tentative de pusher cet modification dans le répertoire distant

Résultat:

  • un message d’erreur apparait signalant le rejet du push.

  • Si on fait git pull:

    • le fichier readme dans la fenêtre git est tagé en jaune
    • Dans l’éditeur, le fichier est modifié: la première modification dans gitlab est reportée.
    • Il va falloir choisir qu’elle modification on veur apporter au projet.

L’état dans RStudio au moment du conflit

Conflit

Conflit

L’ensemble des opérations effectuées:

Résolution du conflit

Résolution du conflit

Dans le fichier readme.md la partie en conflit est balisée et la modification effectuée en amont sur gitlab a été reportée:

<<<<<<< HEAD
  Modification du readme dans RStudio
=======
Modification du readme dans gitlab  
>>>>>>> 7c9442d47454d13263230b659af853eeed84afe5

Résolution du conflit

On va donc devoir choisir entre les deux modifications. Ici on va prendre celle réaliser sur RStudio:

  • On conserve le texte de la modification RStudio
  • On supprime les balises
  Modification du readme dans RStudio
  • On refait l’opération de transfert du local au distant

Conflit

Conflit

Et tout rentre dans l’ordre \(^_^)/

Cela va nous amener tout naturellement à parler du travail sur des branches secondaires à la branche principale.

7.5 Introduction au travail sur les branches

  • Dans un travail en équipe, la question ne se pose même pas…oui. Et quelques soit le partage des rôles: travail sur des fichiers différents ou travail sur des mêmes fichiers. Important: le propriétaire du dépôt devra également travailler sur une branche secondaire…aucun privilège sur ce côté là.
  • En solo, la pratique de travail sur branche(s) secondaire(s) est recommandée. Je pense toutefois que cela dépend de ce qu’on fait:
    • Une documentation Quarto ou Rmarkdown…pas encore convaincu.
    • Un programme d’analyse… pourquoi pas.
    • Le dévelopement d’une application, d’une fonction, d’un package: cela pourra être bien utile lorsqu’on sera amené à tester plusieurs voies de programmation.

En restant en local, on validera les modifications réalisées dans une branche annexe sur la branche principale par une opération de fusion (git merge). On pourra également fusionné dans l’autre sens si des modifications on été faites sur la branche principale (mais ce n’est pas le but). Pour une fusion sur un dépôt distant, par exemple localisé sur Github ou Gitlab, une demande de fusion est effectuée préalablement. Elle est appelée pull request. C’est au propriétaire du dépôt de valider les modifications, et en cas de conflit avec la branche principale la fusion sera complètement bloquée.

Le travail sur branches secondaires permet donc de conserver l’intégrité à tout moment de la branche principale. Sur le même principe une branche secondaire peut se voire attribuer elle-même une ou plusieurs secondaires. Il n’y a donc pas de limite à la ramification.

En cas de conflit lors d’une demande de fusion:

  • En local les éléments de conflit seront reporté sur la branche secondaire, et la fusion ne sera possible qu’une fois sa résolution réalisée. Une remarque s’impose ici. Si on ne travaille pas sur la branche principale, ce qui doit être la pratique lorqu’on développe sur une branche secondaire, aucun conflit ne doit pouvoir se produire.
  • En distant et en équipe avec un pull request, la fusion étant bloquée c’est à la personne qui a fait la demande de fusion de résoudre le conflit en local. Les éléments entrant en conflit avec la branche principale seront reportés sur sont répertoire au niveau local. Une fois le conflit résolu, il devra effectuer un nouveau pull request.

Tout ceci étant à ce stade bien abstrait, on va par l’exemple faire quelques opérations sur branche secondaire avec RStudio: un premier exemple en restant au niveau local et un second exemple avec un pull request sur un dépôt github.

Pour le premier exemple on va utiliser l’interface html dynamique ungit.

7.5.1 Utilisation basique des branches en local

  • Création d’un projet Rstudio
    • New project => New directory => New directory. On coche la case Create with a Git repository
  • Dans le terminal, on s’assure d’en avoir 2. Dans l’un des deux on ouvre l’interface ungit avec tout simplement ungit. On switch sur l’autre terminal.

Création du projet avec répertoire git

Création du projet avec répertoire git

.3 Premier commit sur la branche principale avec la création d’un nouveau fichier

touch prog.R
git add .
git commit -m "first add"

Commit sur la branche principale

Commit sur la branche principale

Création d’une branche

  • Commande git branch
  • Syntaxe: git branch nom_branche

Aller sur la nouvelle branche

  • Commande git checkout
  • Syntaxe: git checkout nom_branche

Ici on va appelé la nouvelle branche modif:

git branch modif
git checkout

Création d’une nouvelle branche et switch sur cette branche

Création d’une nouvelle branche et switch sur cette branche

On va modifier le fichier prog.R

1+1
2+2
3+3

On fait sur la nouvelle branche un commit sur cette modification.

touch prog.R
git add .`
git commit -m "modif prog"

Commit sur une modification de prog.R dans la branche secondaire

Commit sur une modification de prog.R dans la branche secondaire

Fusion dans la branche principale des modifications réalisées dans la branche secondaire

  • On retourne dans la branche principale avec git checkout master

  • On remarque que le fichier prog.R est dans l’état avant sa modification dans la branche modif. Dans l’interface d’ungit l’arborescence est clairement indiquée.

Retour sur la branche principale

Retour sur la branche principale
  • Pour fusionner le commit dans la branche principale:
    • Commande git merge
    • Syntaxe: git merge nom_branche

Ici:

git merge modif

Les modifications apportées au fichier prog.R lui sont alors appliquées dans la branche principale

Fusion des modifications dans la branche principale

Fusion des modifications dans la branche principale

7.5.2 Fusion d’une branche secondaire sur un dépôt distant (Github)

Création d’un dépôt distant - clonage - modification une branche secondaire

  • On va générer un dépôt distant sur github (pull_request)
  • On va le cloner dans un projet R
  • On va créer une branche secondaire (modif). Dans cette branche:
    • On va créer un fichier (prog.R) et le modifier
    • On fait un commit sur ces modifications

Engendrer un pull request sur le dépôt distant

En restant dans la branche secondaire on utilise git push origin nom_branche. Ici:

git push origin modif

En output du terminal, il est indiqué qu’un pull request a été ajouté au dépôt distant.

$ git push origin modif
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 550 bytes | 110.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: Create a pull request for 'modif' on GitHub by visiting:
remote:      https://github.com/mthevenin/pull_request/pull/new/modif
remote:
To https://github.com/mthevenin/pull_request.git
 * [new branch]      modif -> modif

Lorsqu’on retourne sur le dépôt distant:

La branche main sur le dépôt distant

La branche main sur le dépôt distant

Sur le dépôt distant, la branche main n’a pas été modifiée. Seulement le fichier readme généré à la création est présent.
Si on switch sur la branche modif, les fichiers qui ont fait l’objet du commit sont bien présents.

La branche modif sur le dépôt distant

La branche modif sur le dépôt distant

Lorsqu’on clique sur Compare & pull request on est invité à proposer une demande de fusion au propriétaire du dépôt. On valide la demande en cliquant sur Create pull request

Faire une demande de fusion

Faire une demande de fusion

En collaboratif, le propriétaire sera prévenu par mail qu’une demande de fusion a été effectuée. Ici, en solo, la fenêtre de validation s’ouvrira directement. La présence de conflits sera indiquée. Si tout est ok, on valide la fusion la fusion en cliquant sur Merge pull request puis sur Confirm merge. Si un conflit est présent, il ne sera pas possible d’effectuer cette fusion.

Validation de la fusion

Validation de la fusion

Lorsqu’on revient sur la branche principale du dépôt distant

La branche main après fusion

La branche main après fusion

Et sur la branche principale en local?
Elle n’a pas été synchronisée. Même si on ne travaille pas dessus, on peut rapidement effectuer cette synchronisation avec un pull.

git checkout main
git pull

L’output:

$ git checkout main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
thevenin_m@MOB02095 MINGW64 ~/Desktop/pull_request (main)
$ git pull
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), 903 bytes | 53.00 KiB/s, done.
From https://github.com/mthevenin/pull_request
   a8c4daf..15740db  main       -> origin/main
Updating a8c4daf..15740db
Fast-forward
 .gitignore         |  4 ++++
 prog.R             |  3 +++
 pull_request.Rproj | 13 +++++++++++++
 3 files changed, 20 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 prog.R
 create mode 100644 pull_request.Rproj

Sur Gitlab, sous forme d’animation3, à partir du git pull origin nom_branch:

Pull request sur Gitlab

Pull request sur Gitlab

  1. Dans un projet Quarto de type website c’est le cas lorsqu’on réalise une compilation d’ensemble↩︎

  2. Classique pour les fichiers Readme.md↩︎

  3. Avec un petit manque de fluidité sur les manips par manque de pratique sur Gitlab↩︎