Aller au contenu

Contrôle de Version (Notions de Base)

Dans cette unité, nous couvrirons les bases des systèmes de contrôle de version (VCS) en prenant git comme exemple. Nous commencerons par une brève motivation sur pourquoi les solutions traditionnelles de stockage de fichiers sont inadéquates pour gérer le code, illustrerons des scénarios courants de gestion de code avec un VCS et aborderons comment naviguer en toute sécurité dans ces situations de base avec git. La leçon se termine par une courte feuille de triche récapitulant les commandes pour les situations les plus standard.

Résumé de la lecture

Les systèmes de contrôle de version (VCS) permettent à plusieurs développeurs de travailler simultanément sur le même code de manière coordonnée et sans conflit. Git est le VCS de facto et utilise un modèle graphee pour maintenir les versions du code.

Motivation

Pourquoi ne pas simplement placer notre code dans Google Drive / Dropbox / etc. ?

  • Le développement logiciel est une discipline hautement collaborative.
    • La plupart des projets logiciels en entreprise impliquent plus d'un développeur, travaillant constamment sur le même code.
  • Les programmes informatiques sont étroitement couplés.
    • Chaque occurrence d'une variable ou d'une fonction doit être correctement orthographeiée. Un seul changement à un endroit peut facilement briser l'ensemble du programme.
    • La langue humaine est beaucoup plus robuste, il est acceptable que plusieurs personnes modifient un document Google à plusieurs endroits en même temps.
  • Il est donc important que les modifications simultanées de plusieurs développeurs n'interfèrent pas.
Pouvez-vous penser à une solution simple pour éviter un code incohérent ?

Verrouillage : Vous pouvez mettre en place un mécanisme qui permet à un seul développeur à la fois de modifier le code. S'il n'y a pas de concurrence et qu'il n'y a qu'une seule instance de code, il ne peut y avoir de conflits de cohérence. Cependant, pour des raisons pratiques, cette approche n'est plus acceptable.

Dépôts VCS

Tous les systèmes de suivi de version nécessitent un dépôt, c'est-à-dire : une base de données pour suivre l'évolution historique du code. Chaque état suivi est également appelé un "commit".

  • Les progrès sont suivis sous forme de séries d'états.
  • Le travail peut être facilement rétabli à des états antérieurs.
    • Cela est particulièrement utile pour revenir à un état stable lors de démonstrations de logiciels.

Cependant, il existe deux configurations de dépôts : les dépôts centralisés et décentralisés.

Dépôt Central

Les VCS plus anciens comme CVS (Concurrent Version System) et Subversion reposent sur un dépôt central.

  • Il y a exactement un serveur avec toutes les versions historiques du code (dépôt).
  • Les développeurs ont un espace de travail local avec les fichiers du projet et échangent leurs modifications via le serveur.
    • Les développeurs envoient implicitement leur travail au serveur lorsqu'ils créent un nouveau commit.
    • Les développeurs n'ont pas de copie locale de toutes les versions historiques du code.

Dépôts Décentralisés

Le VCS de facto actuel, git, repose sur des dépôts décentralisés.

  • Il peut y avoir, ou non, un serveur. Même une clé USB peut être utilisée pour échanger des commits.
  • Tous les développeurs détiennent une copie complète de toutes les versions historiques du code (dépôt).
    • Les développeurs n'envoient pas implicitement leur travail nulle part lorsqu'ils créent un nouveau commit.

Commit vs Push

Notez que l'échange entre les dépôts montre seulement push/pull au lieu de commit. Dans git, les commits se réfèrent à des instantanés (comme une photo du code à un moment donné), mais ils ne sont pas échangés jusqu'à ce qu'un développeur décide de pousser les commits vers un serveur ou de télécharger des commits d'un autre dépôt.

Le modèle de graphe de Git

Git utilise en interne un modèle de graphe, où les commits définissent des nœuds.

  • Chaque commit, ou nœud, représente une version de votre code.
  • Le dernier commit, également appelé HEAD, est la version la plus récente suivie par git.
  • Pensez à HEAD comme un pointeur vers le commit le plus récent, ou nœud du graphe.

Vous pouvez facilement naviguer dans le de graphe, c'est-à-dire changer le contenu visible sur le disque pour celui d'autres commits.

  • Lorsque vous passez à un autre commit, c'est comme si vous régliez un pointeur dans le graphe vers un commit antérieur.
  • Cela ne change pas la structure du graphe.
    • Rien n'est perdu lorsque vous changez entre les commits.
    • Vous pouvez aller en arrière ou en avant. Le code que vous voyez alors dans votre système de fichiers correspond à l'état du commit correspondant. Mais vous pouvez à tout moment revenir à l'endroit où vous étiez dans le de graphe.
  • Changer le pointeur d'un commit à un autre s'appelle faire un checkout d'un commit.

Les commits sont des sauvegardes

Vous pouvez parfaitement utiliser git uniquement pour vos sauvegardes personnelles. Votre dépôt git local n'a pas besoin de serveur pour fonctionner. En travaillant sur votre projet, vous pouvez régulièrement committer pour construire une trace linéaire de l'historique de votre projet. Si vous devez plus tard revenir en arrière, vous pouvez simplement faire un checkout vers un commit antérieur pour charger une sauvegarde.

Comment ça fonctionne ?

  • Chaque dépôt git a un dossier caché .git
    • Git l'utilise pour stocker la structure du graphe et des informations sur tous les commits.
  • Il est préférable de ne jamais interférer manuellement avec le contenu du dossier .git.
  • Surtout, ne supprimez ni ne renommez le dossier .git.

Extension du graphe local

Lorsqu'un développeur a codé quelque chose de nouveau, par exemple une fonction, il peut créer un nouveau commit et l'ajouter au de graphe.

  • Au fil du temps, à mesure que le projet avance, le graphe de git continue de croître.
  • Dans le cas le plus simple, le de graphe est entièrement linéaire, c'est-à-dire qu'avec chaque commit, la ligne s'allonge un peu :
    ---
    title: Extending graphe with commit
    ---
    gitGraph
    commit id: "1st commit"
    commit id: "2nd commit"
    commit id: "New 3rd commit"  type: HIGHLIGHT

Push (Pousser)

Les commits sont toujours créés dans le cadre d'un dépôt et ne sont pas automatiquement envoyés à d'autres dépôts, c'est-à-dire au serveur.

  • Lorsqu'un développeur étend le graphe de son dépôt local avec un nouveau commit, il doit toujours pousser le nouveau nœud vers le de graphe du serveur.
  • En détail, le processus est le suivant :
    1. Un développeur se synchronise avec le serveur.
    2. Il ajoute ensuite une nouvelle fonctionnalité, c'est-à-dire qu'il crée un commit local nouveau.
      ---
      title: Unsynced git graphes
      ---
      %%{init: {'gitGraph': {'mainBranchName': 'main@git-server'}} }%%
      gitGraph
          commit id: "1"
          commit id: "2"
          commit id: "3"
      %%{init: {'gitGraph': {'mainBranchName': 'main@developer'}} }%%
      gitGraph
          commit id: "1"
          commit id: "2"
          commit id: "3"
          commit id: "New commit" type: HIGHLIGHT
    3. Enfin, ils partagent leur commit en le push vers le serveur.

Branches

Il est également possible de créer délibérément plusieurs versions de votre logiciel, par exemple pour travailler sur des fonctionnalités indépendantes, puis de réunir le travail. Cela peut se faire entièrement localement et s'appelle le branching et le merging.

Dans ce cas, le graphe n'est plus un alignement linéaire de commits, mais devient un véritable de graphe :

---
title: Non-linear commit graphe illustration
---
gitGraph
    commit id: "1"
    commit id: "2"
    branch nice_feature
    checkout nice_feature
    commit id: "3"
    checkout main
    commit id: "4"
    checkout nice_feature
    branch very_nice_feature
    checkout very_nice_feature
    commit id: "5"
    checkout main
    commit id: "6"
    checkout nice_feature
    commit id: "7"
    checkout main
    merge nice_feature id: "8"
    checkout very_nice_feature
    commit id: "9"
    checkout main
    commit id: "10"

Les branches sont un concept avancé de git, que nous aborderons dans une future leçon. Pour l'instant, il suffit de retenir que le de graphe de git est constitué de commits en tant que nœuds et peut être plus complexe qu'une séquence linéaire.

Commandes Git

Que vous souhaitiez initialiser un projet, créer un commit, pousser votre travail vers un serveur ou faire un checkout vers un commit antérieur, la méthode par défaut d'interaction avec git se fait via des commandes.

  • Il est important de comprendre le modèle de graphe sous-jacent et de réfléchir à ce que fait une commande git avant de la taper.
  • Les utilisateurs inexpérimentés essaient souvent simplement d'exécuter des commandes mémorisées, sans comprendre ce qu'elles font.
    • Cela provoque souvent un état de dépôt corrompu et des messages d'erreur compliqués.
    • La solution naïve consiste alors souvent à copier le code ailleurs, à supprimer le projet et à télécharger une nouvelle copie.

Crédits d'image : XKCD

Avertissement

Il existe de nombreux outils de graphe pour interagir avec git. Il est acceptable d'utiliser ces outils, après être devenu compétent avec la ligne de commande. Git est complexe et vous devez avoir une bonne compréhension de son fonctionnement.

Initialiser un projet

N'importe quel dossier peut être transformé en dépôt git.

  • Bien que git soit généralement utilisé pour des projets logiciels, nous pouvons utiliser git pour n'importe quel projet.
  • Imaginons que je veuille utiliser git comme système de sauvegarde pour mes poèmes d'amour personnels.
    • J'ai donc un dossier MyLovePoems, et un fichier unique keksli.txt à l'intérieur :
      MyLovePoems
      └── keksli.txt
      
    • Le poème est une courte et sentimentale œuvre d'art :
      Roses are red
      Violets are blue
      My dearest Keksli
      I love you          ,_     _
                          |\\_,-~/
                          / _  _ |    ,--.
                         (  @  @ )   / ,-'
                          \  _T_/-._( (
                          /         `. \
                         |         _  \ |
                          \ \ ,  /      |
                           || |-_\__   /
                          ((_/`(____,-'
      

      Credits: asciiart.eu

  • Évidemment, je suis régulièrement ému aux larmes par l'intimité émotionnelle de mon poème. Je veux donc m'assurer de ne jamais le perdre lorsque j'expérimente de nouvelles fins et suites.
    • C'est pourquoi j'ai décidé d'utiliser git pour suivre l'évolution de mon poème !
    • C'est aussi simple que d'aller à l'intérieur de mon dossier de projet et de taper : git init
    • La commande crée un nouveau dossier caché .git :
      MyLovePoems
      ├── .git
      │   ├── HEAD
      │   ├── config
      │   ├── description
      │   ├── hooks
      │   │   ├── applypatch-msg.sample
      │   │   ├── commit-msg.sample
      │   │   ├── fsmonitor-watchman.sample
      │   │   ├── post-update.sample
      │   │   ├── pre-applypatch.sample
      │   │   ├── pre-commit.sample
      │   │   ├── pre-merge-commit.sample
      │   │   ├── pre-push.sample
      │   │   ├── pre-rebase.sample
      │   │   ├── pre-receive.sample
      │   │   ├── prepare-commit-msg.sample
      │   │   ├── push-to-checkout.sample
      │   │   └── update.sample
      │   ├── info
      │   │   └── exclude
      │   ├── objects
      │   │   ├── info
      │   │   └── pack
      │   └── refs
      │       ├── heads
      │       └── tags
      └── poem.txt
      

Ne touchez jamais au dossier .git

Git stocke toutes ses données dans ce répertoire, notamment le graphe des commits complet et le "pointeur" vers le nœud sur lequel nous travaillons actuellement. Vous pouvez supprimer l'ensemble du dossier .git si vous êtes sûr de ne plus avoir besoin du suivi des versions. Sinon, éloignez-vous du dossier .git !

Notez que git init ne me place que dans la position de commencer à suivre les versions. Cela signifie :

  • Le graphe git est encore vide.
  • Mon poème n'est pas encore protégé.
  • Nous pouvons vérifier cela en demandant à git de lister les derniers nœuds dans le graphe des commits :
  $ git log
  fatal: your current branch 'main' does not have any commits yet

Configuration initiale

  • Avant de continuer à utiliser git, nous devrions ajouter un nom d'utilisateur et un e-mail.
  • Chaque contribution à un projet est faite par une personne, alors disons à git qui nous sommes et comment nous contacter :
    • git config --global user.name "Maximilian Schiedermeier"
    • git config --global user.email "schiedermeier.maximilian@uqam.ca"

Le drapeau --global indique à git de stocker les paramètres au niveau du système, donc nous n'avons pas besoin de répéter ces étapes pour chaque nouveau dépôt.

Commit

Les commits sont les nœuds dans notre graphe git. Créer un nouveau commit prend trois étapes :

  1. Changer quelque chose sur le système de fichiers. Cela peut être...
    • Modifier le contenu d'un fichier
    • Ajouter un nouveau fichier
    • Supprimer un fichier
  2. Indiquer à git quels fichiers considérer pour le prochain commit :
    • Le graphe est votre billet pour naviguer dans l'historique du code
    • Plus vos commits sont granuleux, plus vous pouvez naviguer précisément
  3. Créer le commit :
    • Créer effectivement un nœud dans le graphe
    • Contenir tous les fichiers considérés (et ignorer tous les autres)
    • Ajouter un court commentaire descriptif

Astuce

La commande git status est un outil utile tout au long du processus. Cette commande vous fournit des informations utiles pour les étapes 1 et 2 : Quels fichiers ont été modifiés et quels fichiers sont suivis par git.

Nous allons maintenant illustrer le processus dans deux scénarios.

Ajouter un nouveau fichier

Pour créer notre premier commit, nous voulons ajouter notre poème existant à un nouveau nœud dans le graphe.

  • Commençons par une vérification pour voir quels fichiers sont présents et lesquels sont suivis :
    • git status
    On branch main

    No commits yet

    Untracked files:
      (use "git add <file>..." to include in what will be committed)
        poem.txt
* _Interprétation_ : git nous indique qu'il y a un fichier `poem.txt` qui n'est pas suivi, c'est-à-dire qu'il n'est pas encore contenu dans le de graphe.
  • Ensuite, nous voulons dire à git que nous souhaitons considérer ce fichier pour le prochain commit.

    • git add poem.txt (git nous a en fait déjà aidés avec cette commande)
    • Vérifions à nouveau ce qui a changé : git status

      On branch main
      
      No commits yet
      
      Changes to be committed:
       (use "git rm --cached <file>..." to unstage)
         new file:   poem.txt
      
    • Interprétation : Tout est bon, git nous dit que le prochain commit contiendra notre poem.txt.

  • Enfin, nous voulons réellement créer notre commit :

    • git commit -m "Première version de mon poème"
          [main (root-commit) 3fc2807] First poem version
           1 file changed, 14 insertions(+)
           create mode 100644 poem.txt
      
    • Interprétation : Un premier commit a été ajouté au graphe.
    • (L'argument -m nous permet d'ajouter un commentaire pour le commit, afin que plus tard il soit plus facile de se souvenir de ce que nous avons contribué.)

Il est toujours bon de vérifier avec git log si notre premier commit apparaît dans l'historique du graphe :

commit 3fc28074200a8503409234f60c1b0ad30fce4d4f (HEAD -> main)
Author: Maximilian Schiedermeier <schiedermeier.maximilian@uqam.ca>
Date:   Sat Aug 24 07:56:19 2024 -0400

    First poem version

Tout semble bon, nous avons créé un premier commit, avec l'ID 3fc2807.

  gitGraph
    commit id: "3fc2807" type: HIGHLIGHT

Checksums

Les IDs de commit ne sont en réalité pas des chaînes aléatoires, mais des checksums SHA-1. Cela signifie qu'ils fournissent une vérification directe de l'intégrité du contenu d'un commit.

Modifier un fichier.

La plupart du temps, nous travaillons sur des fichiers existants, par exemple pour changer une ligne de code.

  • Essayons de modifier quelque chose dans notre poème et de créer un nouveau commit avec les modifications.

    • D'abord, je vais rendre le poème un peu plus adapté aux chats :

    Salmons are red
    Tuna is blue
    My dearest Keksli
    I love you          ,_     _
                        |\\_,-~/
                        / _  _ |    ,--.
                       (  @  @ )   / ,-'
                        \  _T_/-._( (
                        /         `. \
                       |         _  \ |
                        \ \ ,  /      |
                         || |-_\__   /
                        ((_/`(____,-'
    
    * Une fois de plus, nous pouvons demander à git ce qu'il pense de ces changements avec git status.
    On branch main
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
        modified:   poem.txt
    
    no changes added to commit (use "git add" and/or "git commit -a")
    
    * Interprétation : git a détecté que nous avons modifié un fichier qui est déjà dans le de graphe.

  • À moins que nous ne le disions à git, les modifications apportées à poem.txt ne seront pas incluses dans le prochain commit.

    • Comme auparavant, nous disons à git de considérer le fichier du poème :
    • git add poem.txt
    • git status

    On branch main
    Changes to be committed:
      (use "git restore --staged <file>..." to unstage)
        modified:   poem.txt
    
    * Comme auparavant, nous devons toujours créer réellement le nouveau commit : * git commit -m "Improved poem for cat context
    [main 2cdfc6f] Improved poem for cat context
     1 file changed, 2 insertions(+), 2 deletions(-)
    

  • Enfin, nous pouvons vérifier si notre nouveau commit apparaît dans le log :

    • git log --graphe
      * commit 2cdfc6ff084400b42ebe2b93f0fe282b313b73ad (HEAD -> main)
      | Author: Maximilian Schiedermeier <schiedermeier.maximilian@uqam.ca>
      | Date:   Sat Aug 24 10:22:41 2024 -0400
      |         
      |     Improved poem for cat context
      |         
      * commit 3fc28074200a8503409234f60c1b0ad30fce4d4f
        Author: Maximilian Schiedermeier <schiedermeier.maximilian@uqam.ca>
        Date:   Sat Aug 24 07:56:19 2024 -0400
      
           First poem version
      

astuce

Utilisez git log avec l'argument --graphe pour obtenir une visualisation textuelle du graphe git.

Incroyable, nous avons réussi à étendre notre graphe de commits ! Il ressemble maintenant à ceci :

  gitGraph
    commit id: "3fc2807"
    commit id: "2cdfc6f" type: HIGHLIGHT

Fautes de frappe dans les messages

  • Parfois, nous faisons des fautes de frappe dans nos messages de commit.
  • C'est assez facile à corriger, avec :
    git commit --amend -m "New commit message"
    

Checkout

  • Lorsque nous avons étendu le graphe de commits de git avec commit, nous avons implicitement avancé le pointeur, c'est-à-dire que nous avons déjà navigué dans le de graphe.
  • La commande checkout vous permet de naviguer dans le graphe sans le modifier.
    • git checkout 3fc2807
      Note: switching to '3fc2807'.
      
      You are in 'detached HEAD' state. You can look around, make experimental
      changes and commit them, and you can discard any commits you make in this
      state without impacting any branches by switching back to a branch.
      
      If you want to create a new branch to retain commits you create, you may
      do so (now or later) by using -c with the switch command. Example:
      
      git switch -c <new-branch-name>
      
      Or undo this operation with:
      
      git switch -
      
      Turn off this advice by setting config variable advice.detachedHead to false
      
    • Interprétation : Ça a fonctionné, nous sommes maintenant au commit précédent dans le graphe. L'avertissement signifie que nous ne sommes pas à la fin d'une "ligne", ou HEAD.
    • Néanmoins, le contenu de poem.txt est de retour à notre première "sauvegarde".
      Roses are red
      Violets are blue
      My dearest Keksli
      I love you          ,_     _
                          |\\_,-~/
                          / _  _ |    ,--.
                         (  @  @ )   / ,-'
                          \  _T_/-._( (
                          /         `. \
                         |         _  \ |
                          \ \ ,  /      |
                           || |-_\__   /
                          ((_/`(____,-'
      

Nous utilisons également checkout pour revenir à la fin de la ligne principale : git checkout main

Déplacement à la fin d'une ligne

Utilisez toujours le nom de la ligne pour vous déplacer à la fin. Intuitivement, nous pourrions penser qu'utiliser l'ID du commit du dernier commit dans la ligne fait la même chose, mais git ne réattachera HEAD que lorsque nous spécifions le nom de la branche, par exemple main. Donc, dans notre cas, git checkout 2cdfc6f n'est pas la même chose que git checkout main.

Commits détachés

Les commits détachés sont des nœuds qui n'appartiennent à aucune ligne (branche).

  • HEAD se paraphrase comme "le dernier commit sur une ligne".
  • Un HEAD détaché signifie que le code que nous visualisons (déjà checkouté) n'est pas à la fin d'une ligne.

    • Illustration : le carré représente le commit que nous avons checkouté. HEAD est à la fin de la ligne.
    ---
    title: Detached HEAD illustration
    ---
    gitGraph
        commit id: "3fc2807" type: HIGHLIGHT
        commit id: "2cdfc6f (HEAD)"
  • Auparavant, nous avons vu que la commande git commit ajoute un nouveau commit à la fin d'une ligne.

  • C'est pourquoi git nous dit constamment que nous sommes hors piste lorsque nous créons des commits en étant en HEAD détaché :
$ echo "We love Keksli. <3 <3 <3" >> poem.txt
$ git add poem.txt
$ git commit -m "Commit in detached HEAD state"
[detached HEAD 3fc2807] Trying to commit in detached HEAD state
 1 file changed, 1 insertion(+)
  • Les commits effectués en HEAD détaché ne sont connectés à aucune "ligne" (branche), et git ne sait pas quoi en faire.
    • En particulier, git ne nous permet pas de les abandonner (ce qui est une bonne chose, nous risquerions de perdre un travail important !)
    • En étant en HEAD détaché, nous ne pouvons pas naviguer, c'est-à-dire revenir à HEAD.

Pour l’instant : Ne pas commit dans un HEAD détaché

Nous verrons bientôt comment créer correctement des "branches" pour créer des commits sur de "nouvelles lignes".

Corrections

Parfois, il arrive que nous soyons un peu trop pressés et que nous fassions une petite erreur.

Annuler git add

  • Supposons que vous ayez utilisé git add secret-poem.txt et que vous ayez dit à git d'inclure un fichier pour le prochain commit.
  • Mais vous avez fait une erreur et vous ne vouliez en fait pas inclure le fichier.
  • Vous pouvez simplement retirer le fichier avec : git reset secret-poem.txt

Attention

Cela ne fonctionne que si vous n'avez pas encore finalisé le prochain commit.

Annuler git commit

  • Supposons que vous ayez utilisé git pour ajouter et commit les mauvais fichiers.
  • Vous pouvez alors utiliser : git reset HEAD~
  • Le tilde (~) indique à git de retirer le dernier commit du graphe, mais de garder les fichiers du commit intacts.
Quelle est la différence avec un checkout du commit précédent ?

Checkout place le pointeur du graphe au commit précédent, mais ne modifie pas le graphe. Reset retire le dernier commit du graphe.

GitLab

  • Auparavant, nous avons appris que les commits peuvent être envoyés et récupérés d'un dépôt sur un serveur git.
  • Votre université a un serveur git en fonctionnement pour vous : GitLab
  • Un peu pédant, mais soyez précis avec la terminologie :
    • GitLab n'est pas git. GitLab est un logiciel de serveur commercial, git est un outil en ligne de commande pour gérer le graphe de commits !
    • GitLab n'est pas la même chose qu'un seul dépôt git en ligne. De nombreux dépôts différents sont maintenus sur la même instance de serveur GitLab.

Dépôts en ligne

Les serveurs git comme GitLab ont deux objectifs principaux :

  • Fournir une sauvegarde de votre travail.
  • Servir de hubs de synchronisation pour le travail en équipe.

Nous aborderons le travail en équipe dans une prochaine leçon. Pour l'instant, examinons comment utiliser un serveur git comme système de sauvegarde.

Pour la configuration, il y a deux scénarios principaux :

  • Vous avez déjà un dépôt git local, c'est-à-dire que vous avez déjà exécuté git init sur votre ordinateur et que vous avez du code.
    • L'objectif est de créer un dépôt en ligne qui reflète le contenu et le graphe de votre dépôt local.
  • Vous n'avez pas encore de dépôt git local, c'est-à-dire que vous n'avez pas encore exécuté git init sur votre ordinateur et que vous n'avez pas de code.
    • L'objectif est de créer une copie locale (ou de cloner) d'un dépôt git, mis à disposition sur le serveur.

Configuration d'un nouveau dépôt en ligne

Essayons d'apporter une copie de mes poèmes, avec l'ensemble du graphe de commits git au serveur.

  • Utilisez vos identifiants UQAM pour vous connecter à votre compte GitLab personnel.
  • Ensuite, vous pouvez créer votre propre dépôt en ligne :
    • Cliquez sur le signe + en haut à gauche.
    • Sélectionnez Nouveau projet / Dépôt.
    • Sélectionnez Créer un nouveau projet.
    • Donnez-lui un nom, par exemple MyPoems.
    • Donnez-lui un espace de noms, généralement juste votre nom d'utilisateur.
    • Sélectionnez une visibilité, par exemple Privé, afin que seuls les utilisateurs admis aient accès à votre code.
    • Décochez la case créer README (nous nous en occuperons plus tard).

À ce stade, le dépôt est créé, mais vide. Nous allons maintenant vouloir informer git de ce dépôt en ligne vide et envoyer le code et le de graphe au serveur :

  • Informez git du dépôt en ligne :

    • Après la création, la page GitLab montre un bouton bleu Code.
    • Cliquez dessus et copiez la première ligne dans votre presse-papiers. Ce sera quelque chose comme : git@gitlab.info.uqam.ca:max/MyPoems.git
    • Ensuite, utilisez la ligne de commande pour informer git de ce dépôt :

    git remote add origin git@gitlab.info.uqam.ca:max/MyPoems.git
    
    * Jusqu'à présent, nous avons seulement informé git que le dépôt existe. Maintenant, nous devons réellement apporter notre code et le de graphe de commits git au serveur :
        $ git push --set-upstream origin main
        Enumerating objects: 6, done.
        Counting objects: 100% (6/6), done.
        Delta compression using up to 8 threads
        Compressing objects: 100% (4/4), done.
        Writing objects: 100% (6/6), 624 bytes | 624.00 KiB/s, done.
        Total 6 (delta 2), reused 0 (delta 0), pack-reused 0
        To gitlab.info.uqam.ca:max/MyPoems.git
        * [new branch]      main -> main
          branch 'main' set up to track 'origin/main'.
          schieder@imac:MyPoems $
    

Astuce

L'addendum --set-upstream origin main n'est nécessaire que la première fois. À partir de là, notre dépôt git local connaît le serveur associé. De nouveaux commits locaux peuvent être envoyés au serveur avec un simple git push.

Envoyer un nouveau commit au serveur

  • Vous n'avez besoin de configurer le serveur qu'une seule fois.
  • Si je fais d'autres modifications à mon poème, par exemple : echo "<3 <3 <3 <3 <3 <3" > poem.txt
  • Je peux envoyer les commits suivants au serveur avec un simple push :
$ cat poem.txt
Salmons are red
Tuna is blue
My dearest Keksli
I love you          ,_     _
                    |\\_,-~/
                    / _  _ |    ,--.
                   (  @  @ )   / ,-'
                    \  _T_/-._( (
                    /         `. \
                   |         _  \ |
                    \ \ ,  /      |
                     || |-_\__   /
                    ((_/`(____,-'
<3 <3 <3 <3 <3 <3
$ git add poem.txt
$ git commit -m "Added more hearts"
[main f411bbd] Added more hearts
 1 file changed, 1 insertion(+)
$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 292 bytes | 292.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
To gitlab.info.uqam.ca:max/MyPoems.git
   5e2bd29..f411bbd  main -> main

Cloner un dépôt existant

Cloner un dépôt est l'inverse de la configuration d'un dépôt en ligne. Vous clonez lorsque :

  • Le dépôt en ligne existe, et...
  • Vous voulez une copie locale du code et du graphe de commits git.
C'est soit init, soit clone, mais jamais les deux combinés. Pourquoi ?

Git init crée un graphe entièrement nouveau, clone indique de faire une copie liée. Il n'est pas possible de créer un graphe qui soit entièrement nouveau et une copie d'un de graphe existant.

Pour faire une copie locale d'un dépôt en ligne existant :

  • Visitez la page du projet, par exemple le projet MyPoems sur GitLab
  • Cliquez sur le bouton bleu Code et copiez l'une des URL.
  • Ouvrez un terminal et utilisez git clone avec l'URL :
$ git clone git@gitlab.info.uqam.ca:max/MyPoems.git
Cloning into 'MyPoems'...
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 9 (delta 3), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (9/9), done.
Resolving deltas: 100% (3/3), done.

Pas besoin de configurer le serveur

Lorsque vous clonez un dépôt, git connaît déjà le serveur (c'est logique, vous l'avez cloné depuis le serveur). Par conséquent, lorsque vous effectuez de nouveaux commits, vous pouvez directement utiliser git push, sans configuration supplémentaire.

Récupérer plus de commits du serveur

Il est probable que le code sur le serveur évolue et que de nouveaux commits y soient ajoutés.

  • Si votre propre graphe local n'a pas évolué depuis que vous avez cloné, vous pouvez vous synchroniser avec git pull.

Bonnes pratiques

Git est un outil complexe, il est donc important de respecter certaines bonnes pratiques :

  • RÉFLÉCHISSEZ à ce que vous voulez faire dans graphe avant de taper.
  • Commitez souvent (les commits sont des points de contrôle).
    • Commitez de manière précise : évitez git add * ou git add . Ajoutez uniquement les fichiers spécifiques qui vous intéressent.
  • Écrivez des commentaires significatifs.
    • Ne sautez pas le dialogue de message de commit, ne nommez pas vos commits toto, Another commit, ....
  • Ne surchargez pas le dépôt.
    • Git ne peut comprendre que des fichiers textuels.
    • Ne mettez pas de fichiers non textuels (c'est-à-dire des binaires) dans le dépôt, notamment :
      • PDFs
      • PNGs / JPGs
    • Ne mettez pas de fichiers générés dans le dépôt, notamment :
      • Code compilé / fichiers de classe
      • Fichiers JAR
      • Dossier target de Maven
    • Ne mettez pas de fichiers non pertinents dans votre projet :
      • MacOS a tendance à créer des fichiers .DS_Store partout
      • VIM crée des fichiers de cache
      • ...
    • Moins vous avez de déchets dans votre dépôt, mieux c'est.

Gitignore

  • Ajouter des fichiers par accident est trop facile, heureusement il existe un mécanisme de protection.
  • Vous pouvez informer git des types de fichiers, c'est-à-dire des extensions de fichiers qui ne devraient jamais faire partie du dépôt.
  • C'est aussi simple que d'ajouter un fichier : .gitignore.
  • Exemple :
    • Si le fichier .gitignore contient une ligne *.class, git ne vous laissera pas ajouter des classes Java compilées à un commit.

Utilisez un générateur de .gitignore

La plupart du temps, il n'est pas évident de savoir quels fichiers binaires ou générés apparaissent dans un projet, mais vous savez quelles technologies vous allez utiliser, par exemple "MacOS, VIM, Java". Vous pouvez utiliser des générateurs, comme Toptal, pour créer un fichier .gitignore holistique, adapté aux technologies avec lesquelles vous travaillez.

Literature

Inspiration et lectures supplémentaires pour les esprits curieux :