• Git et la Console - partie 2

    Avoir l'air cool en parlant aux machines


    Initiation à la ligne de commande

    Série « Git et la Console »

    Cet article est le deuxième d'une série dédiée à l'apprentissage de Git en ligne de commande.

    Si l'article précédent était consacré à un tour d'horizon des notions liées aux Version Control Systems ainsi qu'à l'installation de Git, celui-ci est l'occasion de faire vos premiers pas avec la ligne de commande grâce à Windows Terminal et la découverte des principales commandes Bash.

    Les autres chapitres sortiront progressivement :

    1. Git, un VCS décentralisé
    2. Initiation à la ligne de commande
    3. Les bases du versionnement avec Git
    4. Manipuler l'historique, les branches et les tags
    5. Fusionner des versions et résoudre les conflits
    6. Communiquer avec les dépôts distants
    7. Travailler à plusieurs efficacement
    8. Conclusion et au-delà

    Sommaire

    1. Les interfaces en ligne de commande
    2. Le terminal Git Bash
    3. Un meilleur terminal : Windows Terminal
    4. Intégrer Git Bash à Windows Terminal
    5. Comprendre la console : l'invite de commande
    6. Découverte des principales commandes bash
      1. Changer de répertoire avec cd
      2. Lister le contenu d'un répertoire avec ls
      3. Créer un fichier avec touch
      4. Créer un fichier avec cat
      5. Créer un dossier avec mkdir
      6. Renommer ou déplacer un fichier ou un dossier avec mv
      7. Copier un fichier ou un dossier avec cp
      8. Supprimer un fichier avec rm
      9. Supprimer un dossier vide avec rmdir
      10. Supprimer un dossier non vide avec rm -rf
    7. Éditer des fichiers avec Vim
    8. Quelques astuces supplémentaires
    9. Configurer votre installation de Git

    1 - Les interfaces en ligne de commande

    En informatique, on distingue les interfaces graphiques (ou GUI pour Graphical User Interface) des interfaces en ligne de commande (ou CLI pour Command Line Interface).

    Parce que nous sommes habitués à utiliser chaque jour des interfaces graphiques reposant notamment sur les possibilités offertes par la souris ainsi que par les concepts de fenêtres, boutons, liens et autres éléments cliquables, on remarque en un clin d'oeil ce qui distingue les interfaces en ligne de commande : elles ne gèrent pas la souris. Donc ne proposent aucune interaction au clic ni au tap sur un écran tactile, pas non plus de glisser-déposer, pas d'images, pas d'éléments graphiques. Tout se fait en lisant et en tapant du texte. Tout se fait avec le clavier.

    Un exemple d'interface en ligne de commande
    Malgré l'absence de souris, certaines interfaces en ligne de commande sont originales et colorées

    Plus précisément, une interface en ligne de commande se manipule en tapant au clavier des commandes. Ces commandes correspondent en fait à des programmes déjà installés sur la machine, que l'interpréteur de commandes va trouver et exécuter pour nous. En installant de nouveaux programmes on peut donc augmenter la liste de commandes que notre machine sait interpréter. En quelques sortes, ces commandes correspondent au vocabulaire utilisé par votre machine.

    Attends, c'est quoi un interpréteur de commandes ?

    Il est lui-même un programme installé sur votre machine. Son boulot, c'est de comprendre les commandes que vous lui envoyez, d'effectuer les tâches demandées et de vous renvoyer un résultat. Il faut comprendre que l'interpréteur ne connait pas les instructions détaillées nécessaires à l'exécution de chaque commande qu'il accepte. A la place, il va établir la correspondance entre les commandes que vous entrez et les autres programmes installés sur votre machine. Si vous entrez une commande qui correspond à un programme que l'interpréteur connait, alors il lui transmet la commande. Et le programme concerné se charge de l'exécution de celle-ci, puis transmet son résultat à l'interpréteur, qui nous le renvoie en retour.

    On utilise très souvent le terme shell pour désigner l'interpréteur de commandes lui-même. Je vous invite toutefois à lire la page Wikipédia pour saisir la nuance entre les deux (en résumé : un interpréteur de commandes est un shell, mais un shell n'est pas nécessairement un interpréteur de commandes).

    Sur Windows, PowerShell est l'interpréteur de commandes par défaut le plus utilisé. L'autre, plus ancien, étant cmd.exe. Bash est quant à lui le plus utilisé sur Linux. Au sein de MacOS, c'est zsh, également utilisé par certaines distributions Linux, qui est désormais l'interpéteur par défaut.

    Okay, et la console dans tout ça c'est quoi ?

    La console, qu'on appelle également terminal, est l'interface que vous utilisez pour communiquer avec l'interpréteur de commandes. Il s'agit le plus souvent d'une application constituée d'une simple fenêtre affichant du texte, vous permettant à la fois de saisir vos commandes et de lire leur résultat.

    Historiquement, il existe des différences entre les notions de console et de terminal, datant des débuts de l'informatique. De nos jours et au sein d'un système d'exploitation actuel, ces différences sont si minimes que les deux termes sont la plupart du temps utilisés comme des synonymes. Je ne dérogerai pas à cet usage ici et continuerai à utiliser l'un ou l'autre terme pour définir la même chose, à savoir l'application que l'on ouvre pour communiquer avec un interpréteur de commandes.

    Sur Windows, le terminal par défaut est conhost.exe. Que vous utilisiez Powershell, cmd.exe ou un WSL, c'est lui qui transmet vos commandes à l'interpréteur puis affiche le résultat. S'il fonctionne bien, le moins qu'on puisse dire est que conhost est un peu... minimaliste. Voire rétro. Il est difficile de continuer à l'utiliser une fois que l'on a testé les alternatives modernes, pleines de fonctionnalités qui rendent beaucoup plus agréable l'environnement en ligne de commande.

    Schéma du fonctionnement de l'environnement en ligne de commande
    Schéma simplifié du fonctionnement d'un environnement en ligne de commande : l'utilisateur saisit des commandes dans le terminal, qui les transmet à l'interpréteur de commandes, lui même transmettant aux programmes concernés. Le parcours s'effectue ensuite dans sens inverse pour faire parvenir la réponse du programme jusqu'au terminal qui pourra l'afficher à l'écran.

    2 - Le terminal Git Bash

    Il est plus courant d’utiliser Git avec Bash, d’où la présence de Git Bash, fourni avec l’installation de Git pour Windows. Git Bash est en fait une surcouche à MinTTY, un émulateur de terminal Linux pour Windows, permettant d’utiliser l'interpréteur de commandes Bash avec la plupart des commandes principales de ce dernier. Git Bash est donc le choix de terminal par défaut à préférer pour utiliser Git sur Windows, bien qu’il existe plein d’alternatives.

    L'avantage pour nous, c'est que Git Bash est livré avec Git. Et comme nous venons d'installer Git dans le module précédent, Git Bash est déjà sur votre machine, prêt à l'emploi !

    Git Bash est déjà installé sur notre machine
    Livré avec Git pour Windows, Git Bash est déjà prêt à servir

    On a donc un terminal :

    • Fourni à l'installation de Git
    • Dédié à l'utilisation de ce dernier
    • Qui permet d'utiliser Bash avec ses commandes principales

    Ce sont des avantages intéressants, mais il en manque. Quand on compare les deux, on constate vite que conhost.exe, le terminal par défaut de Windows, n'a pas grand chose à envier à Git Bash en dehors de la possibilité d'utiliser Bash lui-même. C'est sobre, presque austère, l'expérience utilisateur est très limitée...

    Aperçu de Git Bash
    Git Bash, en compétition avec conhost.exe pour le titre de terminal le moins joli du monde

    Il existe des terminaux bien plus modernes, certains livrés avec leur propre version de Bash. Et d'autres, encore plus intéressants, qui vont nous permettre d'utiliser la version de Bash fournie par Git Bash, tout en profitant d'une interface améliorée et de fonctionnalités avancées. C'est le cas de Windows Terminal, que je vais vous proposer d'installer et de configurer dans les deux prochaines parties.

    Précisons que vous pourriez dès à présent passer à la partie 5 et suivre la suite du module ainsi que tous les suivants en utilisant Git Bash. C'est un terminal parfaitement fonctionnel pour l'usage de Git ainsi que du devops habituel en dev web. Toutes les commandes que je vais vous montrer fonctionnent dedans. Je vous recommande cependant Windows Terminal car il permet de gagner énormément en confort d'utilisation au quotidien.

    3 - Un meilleur terminal : Windows Terminal

    Windows Terminal est un terminal moderne : la première release date de 2019. Et ça se voit en un clin d'œil, tout comme ça se sent très vite à l'utilisation.

    Résumons rapidement ses avantages :

    • Développé par Microsoft
    • Open-source (le code est sur Github)
    • Mis à jour fréquemment, il évolue très vite
    • Permet d'utiliser plusieurs interpréteurs de commandes dans le même terminal
    • Plein de fonctionnalités avancées : onglets, panneaux, menus, raccourcis, personnalisation...
    • Facile à installer et à configurer
    • Bien documenté
    Aperçu de Windows Terminal
    Windows Terminal, le terminal du 21e siècle

    Très facile, l'installation de Windows Terminal se fait via le Microsoft Store.

    Une fois le terminal lancé, la configuration se fait en éditant un fichier settings.json que l'on peut ouvrir en cliquant sur "Paramètres" dans le menu de l'application. Nous allons devoir faire quelques modifications à ce fichier afin d'intégrer Git Bash à Windows Terminal.

    Accès aux paramètres de Windows Terminal
    Ouvrir le fichier de paramètres de Windows Terminal

    4 - Intégrer Git Bash à Windows Terminal

    Le fichier settings.json de Windows Terminal contient trois sections intéressantes :

    • "profiles" : les profils sont des configurations personnalisables pour Windows Terminal. Chaque profil a notamment la possibilité de cibler un interpréteur de commandes particulier. Il est ensuite possible d'ouvrir les profils dans des onglets distincts de l'application. Il est possible de créer, modifier et supprimer plusieurs profils.
    • "schemes" : dans cette partie vous pouvez créer, modifier et supprimer plusieurs modèles de couleurs afin de personnaliser les couleurs utilisées par le terminal. Il est possible d'appliquer un modèle de couleur différent à chaque profil. Vous pouvez trouver des modèles de couleurs existants sur ce site.
    • "actions" : cette partie vous permet de créer, modifier et supprimer des actions utilisables à l'aide de raccourcis claviers personnalisables. Nous n'utiliserons pas les actions dans ce tuto, mais je vous invite à vous y intéresser à l'occasion.

    Et donc si j'ai bien suivi, pour intégrer Git Bash à Terminal il va falloir qu'on crée un profil ?

    Tout juste. La personnalisation d'un profil peut demander du temps, mais afin d'aller au plus simple ici je vais vous recommander la méthode suivante :

    1. Créez un profil minimaliste pour Git Bash, avec seulement les options nécessaires :
      • "name" : Le nom que vous voulez donner à votre profil.
      • "icon" : Une icône à associer à votre profil (vous pourrez trouver celle de Git Bash dans le dossier d'installation de Git).
      • "commandline" : La commande exécutée pour appeler l'interpréteur de commandes de votre choix. C'est ici que vous ciblez l'exécutable Bash de Git Bash.
      • "guid" : Un identifiant unique pour le profil. Vous pouvez en générer un nouveau en ouvrant un profil PowerShell dans un onglet de Terminal et en entrant la commande suivante : [guid]::NewGuid()
    2. Utilisez la partie "profiles"."default" pour personnaliser l'apparence par défaut de Terminal : choix de la police, du modèle de couleurs, de la transparence, d'une image d'arrière-plan, etc. N'hésitez pas à vous référer à la documentation pour connaître en détail toutes les possibilités.
    Générer un guid avec Powershell
    On peut générer un guid facilement avec Powershell

    A ce stade, vous devriez obtenir une configuration des profils ressemblant plus ou moins à ceci :

    
    "profiles": {
        "defaults":
        {
            // Put settings her e that you want to apply to all profiles.
            "closeOnExit":false,
            "colorScheme":"Masta",
            "cursorColor":"#FFFFFF",
            "cursorShape":"bar",
            "fontFace":"Fira Code",
            "fontSize":12,
            "historySize":9001,
            "padding":"0, 0, 0, 0",
            "snapOnInput":true,
            "useAcrylic":true,
            "acrylicOpacity":0.75,
            "startingDirectory" : "C:/wamp64/www",
            "backgroundImage":"C:/Users/matth/OneDrive/Images/Wallpapers/1760900.jpg",
            "backgroundImageOpacity":0.1
        },
        "list":
        [
            {
                "guid": "{00000000-0000-0000-ba54-000000000002}",
                "commandline": "%PROGRAMFILES%/git/usr/bin/bash.exe -i -l",
                "icon": "%PROGRAMFILES%/Git/mingw64/share/git/git-for-windows.ico",
                "name" : "Git Bash"
            },
            {
                // Make changes here to the powershell.exe profile.
                "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
                "name": "Windows PowerShell",
                "commandline": "powershell.exe",
                "hidden": false
            },
            {
                // Make changes here to the cmd.exe profile.
                "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
                "name": "Command Prompt",
                "commandline": "cmd.exe",
                "hidden": false
            },
            {
                "guid": "{b453ae62-4e3d-5e58-b989-0a998ec441b8}",
                "hidden": false,
                "name": "Azure Cloud Shell",
                "source": "Windows.Terminal.Azure"
            }
        ]
    },
    

    Vous pourrez ensuite librement personnaliser davantage d'options pour chaque profil afin de les distinguer.

    Une fois cette configuration effectuée, vous pouvez enregistrer le fichier. Terminal vous propose maintenant la possibilité de lancer le profil Git Bash dans un nouvel onglet.

    Vous pouvez définir le profil par défaut en changeant l'option "defaultProfile" et en lui attribuant comme valeur le guid généré pour votre profil. Ainsi chaque fois que vous lancerez Terminal, c'est un onglet Git Bash qui s'ouvrira par défaut.

    Git Bash est maintenant intégré à Windows Terminal
    Git Bash est maintenant intégré à Windows Terminal

    5 - Comprendre la console : l'invite de commande

    L'invite de commande, aussi appelée prompt, est un texte affiché au début (ou au-dessus) de la ligne permettant de taper une commande dans un terminal. Elle donne en général des informations utiles.

    Avec Git Bash, sa syntaxe est la suivante :

    [utilisateur]@[machine] MSYS [chemin]
    L'invite de commande de Git Bash
    L'invite de commande de Git Bash

    Sur la capture d'écran ci-dessus, l'utilisateur est matth, le nom de la machine est MASTA-AMD et le chemin est ~.

    Le chemin est l'information la plus importante parmi celles fournies par l'invite de commande. Il est important de comprendre que la console permettant de naviguer au sein de l'arborescence de votre système de fichiers, elle est à l'image d'une fenêtre de l'explorateur de fichiers toujours "située" dans un seul dossier à la fois. Ce fameux chemin nous informe donc sur notre emplacement actuel. A tout moment, il est possible d'exécuter des commmandes dans le répertoire actuel, ou bien de changer de répertoire (ce qui se fait également en entrant une commande).

    Ici, ~ est un raccourci pointant vers votre dossier utilisateur. Pour moi il s'agit de C:\Users\matth\. La console est donc, pour moi, actuellement "située dans" mon dossier utilisateur.

    Si vous avez bien compris que la console va vous servir à vous déplacer sur votre machine ET à entrer des commandes, vous êtes prêts pour la suite : la découverte des principales commandes bash.

    6 - Découverte des principales commandes bash

    Liste des commandes présentées

    1. Changer de répertoire avec cd
    2. Lister le contenu d'un répertoire avec ls
    3. Créer un fichier avec touch
    4. Créer un fichier avec cat
    5. Créer un dossier avec mkdir
    6. Renommer ou déplacer un fichier ou un dossier avec mv
    7. Copier un fichier ou un dossier avec cp
    8. Supprimer un fichier avec rm
    9. Supprimer un dossier vide avec rmdir
    10. Supprimer un dossier non vide avec rm -rf

    Changer de répertoire avec cd

    Syntaxe :

    cd [chemin]

    La commande cd est la plus importante de toutes : elle vous permet de vous déplacer sur votre machine. Sans elle, on serait bloqué dans le même dossier et on ne pourrait pas faire grand chose. Très simple à utiliser, il suffit de lui passer en paramètre le chemin du dossier que l'on cherche à atteindre.

    Ce chemin peut être au choix :

    • Absolu : c'est à dire qu'il part de la racine du disque dur (/c/ dans Git Bash)
    • Relatif : c'est à dire qu'il part de l'emplacement actuel

    Par exemple, pour se déplacer dans le dossier Program Files à l'aide d'un chemin absolu, on utilisera la commande suivante :

    cd "/c/Program Files"

    Notez qu'on entoure le chemin de guillemets dès lors que celui-ci contient des espaces.

    Autre exemple, pour se déplacer dans le dossier d'installation de Git en partant de l'emplacement actuel, c'est à dire du dossier Program Files, et donc à l'aide d'un chemin relatif, on utilisera la commande suivante :

    cd Git

    Si l'on veut revenir dans le dossier Program Files, on peut utiliser le raccourci .. qui permet d'atteindre le dossier parent peu importe où l'on se trouve :

    cd ..

    Enfin, si l'on veut revenir dans notre dossier utilisateur, on pourra utiliser le raccourci ~ que nous avions déjà aperçu :

    cd ~
    Changer de répertoire avec la commande cd
    Notez le chemin affiché dans l'invite de commande qui change à chaque fois qu'on se déplace

    Lister le contenu d'un répertoire avec ls

    Syntaxe :

    ls [-options] [chemin]

    Ici comme avec cd, on pourra passer un chemin en paramètre de la commande. Cependant, avec ls le chemin est optionnel : si vous ne le précisez pas, la commande affichera le contenu du répertoire courant.

    Au passage, les règles d'écriture du chemin sont les mêmes que pour la commande cd. Elles s'appliqueront également pour toutes les commandes que nous verrons qui utilisent un chemin comme paramètre.

    Une autre différence par rapport à cd, c'est qu'on va pouvoir passer d'autres paramètres à la commande : des options. Il en existe une multitude, dont vous pouvez obtenir la liste en entrant la commande suivante :

    ls --help

    Cette option --help est disponible pour la majorité des commandes. Très utile quand on a oublié le nom d'une option dont on a besoin 😉

    Les options de ls que je vous recommande sont les suivantes :

    • -l : affiche une liste détaillée, plus lisible et apportant plus d'informations
    • -a : affiche tous les fichiers et dossiers y compris ceux cachés
    • -h : affiche des tailles en Mo, Ko, etc, plutôt qu'en octets

    Il est possible de passer les trois options séparément en paramètre, comme ceci :

    ls -l -a -h [chemin]

    Ou bien, plus rapide, les trois d'un coup comme ceci :

    ls -lah [chemin]
    Afficher le contenu d'un répertoire avec ls
    Affichage du contenu du répertoire courant. Notez la présence des raccourcis .. et . Ce dernier, dont nous n'avions pas encore parlé, nous sera peu utile : c'est un raccourci vers le répertoire courant. Autrement dit un raccourci pour aller où vous êtes déjà.

    Créer un fichier avec touch

    Syntaxe :

    touch [chemin]

    Très simple à utiliser, la commande crée un fichier vide portant le nom spécifié à l'emplacement spécifié.

    Par exemple pour créer un fichier nommé fichier vide.txt dans le répertoire courant :

    touch "fichier vide.txt"

    Où pour créer un fichier nommé test à la racine du disque dur (en utilisant un chemin absolu) :

    touch /c/test

    Notez qu'il est possible de créer un fichier avec ou sans l'extension de votre choix. Une extension de fichier n'est, après tout, que la fin d'un nom de fichier, elle fait partie de ce dernier. A vous donc d'en inclure une ou non. Par exemple, pour créer un fichier HTML on pourrait faire :

    touch index.html

    Le fichier sera de toute façon créé vide. C'est ce que nous écrirons à l'intérieur qui en fera un vrai fichier HTML.

    Créer un fichier avec cat

    Syntaxe :

    cat > [chemin]

    Méthode alternative à touch, la différence est qu'avec cat nous allons directement pouvoir saisir le contenu de notre fichier depuis la console.

    En effet après avoir entré la commande, l'invite de commande ne réapparaît pas. C'est parce que l'exécution de la commande cat n'est pas terminée. Pourtant, vous pouvez saisir du texte. Mais pas de commande. Tout ce que vous tapez là sera écrit dans le fichier que vous souhaitez créer. Lorsque vous avez terminé d'écrire, il faut utiliser le raccourci clavier CTRL+D pour valider, ce qui créera votre fichier et terminera l'exécution de la commande. Vous pouvez à la place utiliser CTRL+C, ce qui annulera votre saisie (le fichier sera quand même créé, mais vide).

    Par exemple si l'on voulait créer un fichier nommé nouveau-fichier dans le répertoire parent, on pourrait utiliser le raccourci .. :

    cat > ../nouveau-fichier

    Si l'on saisit le texte "Hello World", ce texte sera inscrit dans notre fichier.

    Créer un fichier avec touch ou cat
    Exemples de créations de fichiers avec les commandes touch et cat. On vérifie ensuite la présence des fichiers grâce à ls.

    Créer un dossier avec mkdir

    Syntaxe :

    mkdir [-options] [chemin]

    Rien de très particulier avec cette commande. Le chemin fonctionne comme d'habitude, c'est à dire que vous pouvez créer un dossier à un emplacement différent de votre emplacement actuel.

    Il y a une option que je vous recommande, il s'agit de -p. Elle permet de créer l'ensemble des dossiers du chemin s'ils n'existe pas. Ce qui vous permet de créer des dossiers "sur plusieurs niveaux".

    Par exemple, en entrant la commande suivante :

    mkdir -p sous-dossier-1/sous-dossier-2

    Si sous-dossier-1 n'existe pas déjà dans le répertoire courant, il sera créé. Ensuite, sous-dossier-2 sera créé à l'intérieur de sous-dossier-1

    Créer un dossier avec mkdir
    Créations de dossiers avec mkdir et vérification de leur présence avec ls.

    Renommer ou déplacer un fichier ou un dossier avec mv

    Syntaxe :

    mv [-options] [ancien-chemin] [nouveau-chemin]

    Très pratique, la commande mv permet de déplacer aussi bien un fichier qu'un dossier. Le nouveau chemin que vous passez en paramètre indique le nouvel emplacement et le nouveau nom du fichier ou dossier concerné. Ainsi, il est possible de simplement renommer un fichier sans changer son emplacement.

    Par exemple, si l'on voulait renommer fichier.txt en fichier-renommé.txt, il suffit d'entrer la commande suivante :

    mv fichier.txt fichier-renommé.txt

    Si, ensuite, on voulait déplacer le fichier fichier-renommé.txt dans le dossier parent, on pourrait utiliser la commande suivante :

    mv fichier-renommé.txt ../fichier-renommé.txt
    Renommer et déplacer un fichier avec mv
    Exemple de renommage et de déplacement d'un fichier avec la commande mv.

    Pour information, il existe plusieurs options pour la commande mv, essentiellement liées à la gestion de conflits (quand vous essayez de déplacer un fichier ou dossier à un emplacement qui contient déjà un fichier ou dossier). Comme d'habitude, je vous invite à regarder ces options de plus près en affichant l'aide de la commande :

    mv --help

    Copier un fichier ou un dossier avec cp

    Syntaxe :

    cp [-options] [chemin-source] [chemin-copie]

    Cette commande fonctionne de façon similaire à mv. Cependant, deux options sont utiles :

    • -r : indispensable si vous voulez pouvoir copier des dossiers
    • -u : si jamais le fichier cible existe déjà, il ne sera remplacé par une copie du fichier source que si ce dernier est plus récent

    Exemple de copie dans le répertoire courant du fichier fichier-renommé.txt (précédemment déplacé dans le répertoire parent) :

    Copier un fichier avec cp
    Exemple de copie d'un fichier avec cp et vérification de la présence du fichier copié avec ls.

    Pour copier le dossier sous-dossier-1 il faudrait utiliser l'option -r :

    cp -r sous-dossier-1 sous-dossier-1-copie

    On pourra avec ls vérifier que le contenu du dossier a également été copié. C'est le but de l'option -r : effectuer une copie récursive du dossier, son contenu, tous ses sous-dossiers et tous leurs contenus.

    Copier un dossier avec cp
    Exemple de copie d'un dossier avec cp et vérification de la présence du dossier copié et de son contenu avec ls.

    Supprimer un fichier avec rm

    Syntaxe :

    rm [-options] [chemin]

    L'option -i permet de demander une confirmation avant la suppression. Tapez "y" ou "yes" puis Entrée pour valider. Si vous n'utilisez pas l'option -i, le fichier spécifié sera instantanément supprimé.

    ⚠️ Attention : les fichiers supprimés avec rm ne vont pas dans la corbeille de Windows, ils disparaissent !

    A titre d'exemple, si l'on veut supprimer le fichier fichier vide.txt avec une demande de confirmation, on entrera la commande suivante :

    rm -i "fichier vide.txt"
    Supprimer un fichier avec rm
    Exemple de suppression d'un fichier du répertoire courant avec rm et vérification de l'absence du fichier avec ls.

    Supprimer un dossier vide avec rmdir

    Syntaxe :

    rmdir [-options] [chemin]

    Ne fonctionne que sur les dossiers vides.

    L'option p permet de supprimer l'ensemble des dossiers du chemin s'ils sont vides, ce qui vous permet de supprimer des dossiers "sur plusieurs niveaux".

    Par exemple, en entrant la commande suivante :

    rmdir -p sous-dossier-1-copie/sous-dossier-2

    D'abord, si sous-dossier-2 est vide il sera supprimé. Puis, si sous-dossier-1-copie est vide à son tour (s'il ne contenait que sous-dossier-2), il sera lui aussi supprimé.

    Supprimer un dossier vide avec rmdir
    Exemple de suppression de dossiers du répertoire courant avec rmdir et vérification de leur absence avec ls.

    Supprimer un dossier non vide avec rm -rf

    Syntaxe :

    rm [-r] [-f] [chemin]

    ⚠️ Attention : commande très dangereuse si mal utilisée, à manier avec une extrême précaution !

    L'option -r fonctionne de la même façon que pour la commande cp : elle amène la récursivité, donc la suppression de tous les sous-dossiers contenus dans le dossier ciblé... ainsi que de leurs contenus !

    L'option -f quant à elle, force la suppression. C'est-à-dire qu'avec cette option, la commande ne vous demandera pas de confirmation : elle supprimera tout sans broncher.

    La commande avec les deux options ensemble, à savoir rm -rf, est donc très pratique lorsque l'on veut supprimer d'un coup un dossier et tout son contenu. Mais elle peut aussi s'avérer très dangereuse si l'on se trompe dans le chemin que l'on passe en paramètre...

    Pire encore : si on utilise comme chemin la racine du disque dur... à savoir / sur Linux et MacOS, et /c/ sur Windows avec Git Bash... Alors on demande à la commande d'effacer TOUS les dossiers et fichiers de notre disque dur. Et ce sans la moindre confirmation si on a utilisé l'option -f.

    ⚠️ J'insiste : vous l'avez compris, il n'y a rien de tel qu'un simple rm -rf / pour détruire entièrement tout un système. Autant vous dire que je ne me suis jamais amusé à essayer. Et je vous conseille très fortement de suivre mon exemple si vous ne voulez pas détruire votre système d'exploitation et perdre toutes vos données.

    Un exemple de ce qu'il arrive à Ubuntu quand on entre la commande interdite

    Au quotidien, si l'on fait très attention, utiliser la commande reste pratique, quand on est sûr de ce que l'on supprime. A titre d'exemple, nous pourrions supprimer le dossier sous-dossier-1 et tout son contenu, en entrant simplement :

    rm -rf sous-dossier-1
    Supprimer un dossier non vide avec rm -rf
    Exemple de suppression d'un dossier non vide avec rm -rf, puis vérification de l'absence du dossier avec ls.

    ...et voilà pour la présentation des principales commandes Bash !

    Il en existe bien évidemment beaucoup d'autres. Mais je vous conseille de vous entrainer déjà un peu avec ces bases là avant d'aller plus loin. Vous habituer aux quelques commandes présentées ici vous permettra dans un premier temps d'être à l'aise avec la console, après quoi vous pourrez progressivement aller plus loin.

    Command-line master illustration
    Maintenant que vous connaissez les principales commandes Bash, votre parcours pour devenir Grand Maître de la Ligne de Commande peut commencer !

    7 - Éditer des fichiers avec Vim

    Vim est un éditeur de texte en ligne de commande. Une sorte de notepad pour la console. La souris n'étant pas disponible dans le terminal, Vim ne propose pas d'interface graphique, seulement une interface en ligne de commande. Pas de boutons, pas de menus... Dans Vim on fait tout avec des commandes et des raccourcis clavier.

    Attends, j'en ai entendu parler de ton truc, ça a l'air super compliqué... j'ai vraiment besoin d'apprendre ça pour utiliser Git ?

    Réponse courte : Non 😊

    Réponse plus sérieuse : Il est vrai que Vim est réputé difficile à apprendre, et il est vrai qu'il n'est pas indispensable à l'utilisation de Git. Cependant, pour utiliser confortablement le terminal au quotidien, il vous faut être capable d'éditer rapidement des fichiers. Car c'est un besoin très fréquent, pour lequel il peut être fastidieux d'avoir sans cesse à alterner entre votre terminal et un éditeur de texte avec interface graphique. Dans la console, on a souvent besoin d'éditer rapidement de petits fichiers, par exemple des fichiers de configuration. Vous pouvez également avoir besoin d'un éditeur dans un environnement ssh ou autre environnement dépourvu d'interface graphique. Enfin, Git lui-même a parfois tendance à attendre de vous que vous utilisiez Vim et à le lancer pour vous (selon l'éditeur que vous avez configuré lors de l'installation à la fin du module précédent). Il peut donc arriver qu'on ait besoin au minimum de savoir quitter Vim lorsqu'il est ouvert, ce qui n'est pas si intuitif que ça.

    Trapped in Vim by CommitStrip
    Quitter Vim, un vrai traumatisme pour certains développeurs restés coincés dedans plusieurs jours

    Pour tous ces besoins, une connaissance des bases est intéressante. Lancer et quitter l'éditeur évidemment, mais également saisir du texte et sauvegarder un fichier. A savoir les bases les plus élémentaires possibles. Le kit de survie minimum.

    Si Vim vous intéresse, il existe plein de livres et autres cours en ligne qui lui sont consacrés. L'éditeur offre beaucoup de fonctionnalités à découvrir, et est réputé pour permettre d'atteindre une vitesse de travail très perfomante une fois qu'on le maîtrise bien, ce notamment grâce à ses raccourcis clavier qui ont été pensés pour être les plus logiques possibles.

    Évidemment ça c'est à condition de s'y intéresser pour de vrai. Quand on ne voit que les bases, comme nous allons faire, il reste une vraie courbe d'apprentissage avant de réellement pouvoir prétendre à maîtriser l'éditeur. Je vous rassure, on s'en sort très bien en tant que développeur sans être un expert Vim.

    Je vous propose donc de faire ensemble et très rapidement le tour de ces quelques notions faisant partie du "kit de survie" avec Vim.

    Lancer Vim

    Syntaxe :

    vim [-options] [chemin]

    On n'abordera pas les options de la commande Vim dans le cadre de ce tuto, mais il en existe plein. Pour l'instant, nous nous contenterons donc du plus simple :

    vim [chemin]

    Si le fichier correspondant au chemin existe, Vim va l'ouvrir. Sinon, il va ouvrir un fichier vierge, et se préparer à l'enregistrer à l'emplacement indiqué par le chemin au moment où vous lui direz.

    Pour l'exemple, nous allons ouvrir un nouveau fichier au nom de nouveau fichier.txt :

    vim "nouveau fichier.txt"
    Ouvrir un nouveau fichier avec Vim : la commande permettant de lancer l'éditeur
    Ouvrir un nouveau fichier avec Vim : l'éditeur une fois ouvert
    Ouverture d'un nouveau fichier avec Vim

    Passer en mode insertion et saisir du texte

    La première chose à comprendre avec Vim est qu'il compense l'absence d'interface graphique par des modes. Les deux modes principaux sont :

    • Le mode commande : C'est le mode dans lequel Vim s'ouvre par défaut. Il permet de saisir des commandes internes à l'éditeur afin de manipuler le fichier ouvert et l'éditeur lui-même.
    • Le mode insertion : C'est le mode qui nous permet de saisir du texte dans le fichier.

    On alternera donc fréquemment entre les modes commande et insertion selon nos besoins.

    Le mode commande étant le mode par défaut, votre éditeur devrait actuellement être dans ce mode là. Pour passer en mode insertion il faut utiliser un raccourci clavier : la touche i.

    Une fois le mode insertion activé, le texte -- INSERTION -- s'affiche en bas à gauche de l'éditeur, et un curseur de texte clignote dans l'éditeur, vous permettant de saisir le contenu de votre fichier.

    Passer en mode insertion avec Vim
    Le mode insertion de Vim

    Quitter le mode insertion, sauvegarder le fichier et quitter Vim

    Pour quitter le mode insertion rien de plus facile : on utilise la touche Echap.

    Nous sommes donc de retour dans le mode commande. Nous pouvons maintenant entrer la commande permettant de sauvegarder le fichier : :w. Si le fichier existe déjà et doit être remplacé, Vim voudra une confirmation de notre part, ce qu'on peut lui indiquer en plaçant un point d'exclamation à la fin de la commande, comme ceci : :w!

    Pour quitter Vim il faut utiliser la commande :q. Si vous voulez quitter sans enregistrer vos modifications, Vim voudra également une confirmation de votre part, ce que vous pouvez lui indiquer toujours en plaçant un point d'exclamation à la fin de la commande : :q!

    Si jamais vous voulez sauvegarder et quitter, vous pouvez utiliser les deux commandes à la fois, comme ceci : :wq. Avec bien évidemment l'équivalent :wq! pour confirmer le remplacement du fichier si nécessaire.

    Enregistrer le fichier et quitter Vim
    La commande que tant ont cherché...

    Et c'est tout pour les bases rudimentaires de Vim. Il y aurait bien plus à découvrir mais je laisse ça à votre curiosité. Le module d'aujourd'hui est déjà très long et Vim n'est pas le sujet de ce tuto.

    Cependant avec ce qu'on vient de voir vous connaissez l'essentiel pour que cela soit pratique au quotidien. Besoin d'éditer un fichier rapidement ? C'est fait en quelques secondes avec Vim, et sans quitter le terminal !

    Il est à noter que deux autres éditeurs en ligne de commande sont très populaires : Emacs et Nano, jetez-y un oeil à l'occasion.

    8 - Quelques astuces supplémentaires

    Nous avons presque fini pour ajourd'hui, et ça fait déjà pas mal de nouvelles notions !

    Il est temps de les compléter avec quelques astuces qui vont vous rendre l'utilisation de la console plus agréable :

    • Windows Terminal propose un menu très pratique dans lequel vous pourrez retrouver l'ensemble des fonctionnalités de l'application, accessible avec le raccourci clavier CTRL + MAJ + P
    • Vous pouvez naviguer dans l'historique des commandes saisies avec les flèches et du clavier. C'est un vrai gain de temps lorsque l'on doit entrer de nouveau une commande longue à écrire, n'hésitez pas à en abuser.
    • Chaque fois que vous tapez un chemin, vous pouvez utiliser l'auto-complétion avec la touche (tabulation). Là aussi c'est un réel gain de temps au quotidien.
    • Copier du texte depuis un terminal : CTRL + Insert
    • Coller du texte dans un terminal : MAJ + Insert
    • Annuler une commande en cours (qui prend du temps) : CTRL + C
    • Obtenir de l'aide sur une commande : [commande] --help
    • Effacer les résultats des commandes précédentes : clear
    • Entrer deux commandes (ou plus) à la suite : [commande1] && [commande2] && [...]
    • Écrire le résultat d'une commande dans un fichier : [commande] > [chemin]

    Prenez le temps de vous exercer et de vous familiariser avec tout ceci, vous verrez que votre productivité et votre confort vous en remercieront !

    Definitely not lazy par CommitStrip
    La recherche du gain de temps a parfois ses limites, CommitStrip l'a bien compris...

    9 - Configurer votre installation de Git

    Dernière étape pour aujourd'hui, histoire de nous recentrer un peu sur notre sujet initial : maintenant que nous savons utiliser la console, nous allons pouvoir l'utiliser pour configurer Git. Rassurez-vous, c'est très simple : il faut entrer deux commandes.

    Le but de ces deux commandes est d'indiquer à Git votre nom et votre adresse email. Ces informations seront utilisées par Git pour signer vos commits c'est à dire votre travail. Ce sont ces informations qui permettront aux autres développeurs du projet de savoir que vous êtes l'auteur de votre code.

    Configuration de votre nom d'utilisateur (remplacez "Prénom Nom") :

    git config --global user.name "Prénom Nom"

    Configuration de votre nom d'utilisateur (remplacez prenom.nom@email.com) :

    git config --global user.email prenom.nom@email.com

    Si jamais vous avez un compte Github, Bitbucket ou Gitlab, il est recommandé d'indiquer à Git les mêmes nom d'utilisateur et mot de passe que sur votre compte.

    Grâce à l'option --global cette configuration est valable pour l'ensemble de votre machine (donc à faire une seule fois par installation de Git). Il est cependant possible de configurer ces valeurs pour un projet Git spécifique, en entrant les mêmes commandes sans l'option --global, dans le dossier du projet.

    Configuration de Git
    Configuration de Git en ligne de commande

    Et voilà pour aujourd'hui !

    Dans le module suivant, nous pourrons enfin aborder la pratique avec Git en créant notre premier dépôt et nos premiers commits. D'ici là, prenez le temps de vous familiariser avec la console.

    J'espère que tout ceci vous aidera. N'hésitez pas à me signaler les erreurs, incohérences et/ou typos qui pourraient rester dans l'article, il est long donc je n'ai peut-être pas tout vu. Merci 😊


  • Git et la Console - partie 1

    Découvrir Git en toute tranquillité


    Git, un VCS décentralisé

    Série « Git et la Console »

    Cet article est le premier d'une série dédiée à Git, dans le but d'offrir une synthèse des notions essentielles à comprendre lorsqu'on le découvre, ainsi que quelques bonnes pratiques à respecter. Je ne prétends pas livrer ici une alternative à la documentation officielle, qui a le mérite d'être bien écrite et devrait être lue en priorité. Voyez plutôt ces quelques chapitres comme un complément à votre apprentissage. Complément qui je l'espère pourra vous aiguiller un peu quant à la façon dont vous utiliserez Git.

    Après une découverte progressive des bases, nous évoquerons les méthodes efficaces parmi celles qui existent, comment s'adapter, comment régler les cas de conflits, comment les prévenir. Nous verrons pourquoi une bonne compréhension des mécanismes internes à Git lui-même facilite grandement l'adoption de toutes ces solutions.

    Au passage, ce sera aussi l'occasion de découvrir les bases de la console puisque nous manipulerons Git exclusivement en ligne de commande. Et tant qu'à faire nous utiliserons une console moderne avec Windows Terminal.

    Les chapitres suivants sortiront progressivement :

    1. Git, un VCS décentralisé
    2. Initiation à la ligne de commande
    3. Les bases du versionnement avec Git
    4. Manipuler l'historique, les branches et les tags
    5. Fusionner des versions et résoudre les conflits
    6. Communiquer avec les dépôts distants
    7. Travailler à plusieurs efficacement
    8. Conclusion et au-delà

    Sommaire

    1. Le versionnement en informatique
    2. Les Version Control Softwares
    3. Le VCS le plus utilisé : Git
    4. Les avantages et inconvénients de Git
    5. Installation de Git

    1 - Le versionnement en informatique

    La Gestion de versions, vulgairement appelée versionnement, consiste à créer et gérer différentes versions d'un même projet.

    Ces versions peuvent être des étapes dans la vie du projet, par exemple v1.0.0, v2, etc. Pour les besoins du tuto, nous appellerons ce type de versions des versions chronologiques. Quand on travaille avec Git, elles correspondent aux tags.
    Mais les versions peuvent aussi être des versions spécifiques du projet dédiées à des besoins précis, par exemple master, develop, test, etc. Pour les besoins du tuto, nous appellerons ce type de versions des versions spécifiques. Quand on travaille avec Git, elles correspondent aux branches.
    Nous découvrirons ensemble ces concepts dans le module 4.

    L'ensemble des versions constitue un historique, nous permettant de suivre l'évolution du projet à travers le temps, depuis sa création jusqu'à son état actuel, en passant par toutes les versions alternatives, temporaires ou spécifiques qui pourraient exister.
    On cherchera souvent à naviguer au sein de cet historique, c'est à dire à modifier notre projet pour qu'il corresponde à une version précise. Avec git, c'est la commande git checkout qui nous permettra ceci. Nous verrons également cette commande dans le module 4.

    On aura aussi régulièrement besoin de fusionner différentes versions, ce qui pourra éventuellement entrainer des conflits qu'il faudra savoir résoudre. Le module 5 sera dédié à ces notions avec la découverte des commandes git merge et git rebase.

    Enfin, l'intérêt du versionnement est bien souvent de faciliter le travail à plusieurs. Les modules 6 et 7 se concentreront sur ce besoin en abordant la communication avec les dépôts distants et en présentant plusieurs workflows permettant d'organiser le travail en commun.

    Tous ces besoins peuvent s'avérer complexes à gérer au quotidien, surtout sur de gros projets avec beaucoup de développeurs impliqués. C'est pourquoi on a recours à des solutions logicielles. On parle ici des fameux Version Control Softwares (ou Systems), dont Git est le représentant le plus populaire.

    2 - Les Version Control Softwares

    Les Version Control Softwares (ou Systems) sont nombreux, et bien plus anciens que Git lui-même. S'ils sont historiquement très utilisés dans le logiciel libre et l'open-source, de nos jours leur usage s'est généralisé à l'ensemble du développement informatique. Bien que la plupart d'entre-eux utilisent nombre de concepts communs, chacun a ses particularités le rendant plus ou moins adapté aux différents projets et aux différentes équipes. Par exemple certains sont centralisés quand d'autres, à l'image de Git, sont décentralisés (ou "distribués"). L'apparition de Git a cependant permis de gommer les quelques lacunes et faiblesses de ses prédécesseurs, le propulsant jusqu'à la position de VCS le plus populaire et le plus utilisé à travers le monde.

    Ce que l'on attend d'un bon VCS c'est avant tout de satisfaire les besoins évoqués précédemment. À savoir :

    • On doit pouvoir créer facilement de nouvelles versions et de nouvelles modifications
    • On doit avoir accès à un historique compréhensible : on doit pouvoir savoir facilement qui a fait quoi et quand
    • On doit pouvoir facilement revenir en arrière, effacer des modifications, en fusionner...
    • Les cas de conflits entre différentes versions doivent être les moins fréquents possibles, et simples à résoudre
    • Le travail à plusieurs et à distance doit être facilité en toute circonstance et pour tout type d'équipe

    Pour satisfaire ces besoins, beaucoup de VCS ont recours aux principes de commit, d'historique, de tag et de branche.

    Les commits, en français appelés simplement modifications, sont des enregistrements des modifications apportées aux fichiers du projet. On peut en quelque sorte les considérer comme des sauvegardes du travail effectué. C'est la suite des commits dans le temps qui nous permet d'accéder au fameux historique de l'évolution de notre projet.

    Comme on l'a vu précédemment, les tags correspondent aux versions chronologiques du projet. Ils sont un moyen d'identifier un commit précis comme correspondant à une version précise. Il n'est pas nécessaire de créer un tag pour chaque commit : c'est vous qui décidez quand un commit doit correspondre à une version, version que vous définissez, en créant un tag avec un numéro de version : v0.0.1 > ... > v1.0.0 > v1.0.1 > ... > v1.1.0 > ...

    Les branches quant à elles sont des versions "concurrentes" ou "parallèles" d'un même projet, c'est-à-dire les versions spécifiques dont nous parlions précédemment. Ces branches peuvent coexister et/ou être fusionnées.

    Par exemple : la branche master ou main représente souvent la version stable d'un projet. Celle testée, sans bug, utilisable. Par opposition, la branche develop représente souvent la version qui centralise tous les développements en cours. Typiquement, lorsque ces développements sont terminés et testés, on voudra les fusionner dans la branche master afin de faire évoluer la version stable du projet.

    Un bon VCS doit donc faciliter toutes ces opérations, le tout sans nous limiter dans les possibilités d'évolution du projet et des différentes versions le constituant.

    Mais un bon VCS doit également être rapide. Une gestion de versions correctement effectuée a recours à des manipulations très fréquentes. On doit souvent sauvegarder notre travail, souvent récupérer le travail des autres, souvent fusionner les deux ensemble. Comme ces opérations sont très fréquentes dans la journée d'un développeur, il est rare que ce dernier apprécie de perdre du temps chaque fois que ces étapes se renouvellent.

    3 - Le VCS le plus utilisé : Git

    Linus Torvalds, créateur de Git et du noyau Linux
    Linus, Père spirituel des Manchots

    C'est à Linus Torvalds, le papa du noyau Linux, que l'on doit également la création de Git.

    L'équipe de développement du noyau Linux versionnait historiquement son code à l'aide du VCS BitKeeper, jusqu'à ce que l'éditeur de celui-ci cesse brutalement de fournir la version gratuite en 2005. Linux étant un projet libre, il était important pour l'équipe de remplacer BitKeeper par un outil qui ne soit pas propriétaire. Ils étaient donc dans le besoin d'une alternative. Et c'est ainsi que Linus commença à travailler sur le développement de Git, le VCS qui surpassera bientôt tous les autres.

    Ce qui a fait le succès de Git, c'est à la fois sa souplesse dans la gestion des branches, sa rapidité d'exécution, et son modèle distribué (ou décentralisé) qui facilite grandement le travail à plusieurs. Ainsi que bien évidemment le fait que son code soit libre et accessible à tous.

    Enfin, c'est l'incontournable Github qui apporta l'ultime vague de popularité à Git. Aujourd'hui détenu par Microsoft, Github est le site qui héberge et centralise la majorité des projets libres et open-source du monde. Ce qui n'est possible que parce que le site s'appuie très fortement sur le VCS créé par Linus Torvalds. Github, par son importance, constitue à lui seul un argument en faveur d'une maîtrise de Git pour tout développeur actuel.

    Logo du VCS Git
    Git, un VCS pour les gouverner tous

    4 - Les avantages et inconvénients de Git

    Nous avons déjà évoqué plusieurs raisons du succès de Git, mais résumons un peu ses avantages par rapport aux autres VCS :

    • Par sa souplesse, Git rend très facile de créer et travailler avec des branches
    • Git compare nos fichiers ligne par ligne et non fichier par fichier
    • Il propose une gestion intelligente et non-bloquante des conflits
    • Il est décentralisé (ou "distribué") : il n'y a pas de serveur principal
    • En conséquence de l'aspect décentralisé, Git est très facile à mettre en place
    • Git est très rapide, c'est un plaisir de l'utiliser
    • Le plus : la documentation officielle est très bien faite

    Ce serait presque le VCS parfait s'il ne venait pas avec trois inconvénients principaux :

    • L'aspect décentralisé amène majoritairement des avantages. Mais un grand pouvoir implique de grandes responsabilités : s'il n'y a pas de serveur principal, alors chaque participant au projet peut tout faire. Tout le monde a la possibilité de fusionner des versions aussi bien que de les faire disparaître. C'est-à-dire que chaque participant au projet a la possibilité de faire disparaître du code... Une simple erreur pouvant coûter très cher (littéralement : votre code est le produit de vos heures de travail), il convient d'utiliser Git avec prudence et en sachant ce que l'on fait.
    • Git étant très souple, il existe souvent plusieurs façons d'aboutir au même résultat, ou à un résultat similaire. En revanche dès lors que l'on travaille à plusieurs sur le même projet, il devient très important que chacun utilise la même méthode que les autres. Des conventions et des bonnes pratiques sont donc très utiles, et sont susceptibles d'être différentes à chaque équipe et/ou projet. Dans le module 7 nous aborderons les méthodes les plus utilisées ainsi que les bonnes pratiques que l'on peut en tirer.
    • Git est, c'est un fait, plus difficile à comprendre et à maîtriser que d'autres VCS. Son apprentissage demande sérieux, implication et mise en pratique dans la précaution. C'est en partie ce qui me pousse à écrire ce tuto/cours, j'espère qu'il pourra compléter cet apprentissage parfois compliqué.
    La formation du nouveau - web comic par CommitStrip
    CommitStrip rendant hommage à Git

    5 - Installation de Git

    Pour installer Git sous Windows, vous pourrez trouver un programme d'installation à télécharger sur sur le site officiel.

    L'installeur vous demande de choisir plusieurs choses, nous allons donc les passer en revue ensemble :

    Première étape de l'installation de Git
    Pour cette première étape "Select Components", vous pouvez tout cocher par défaut. Si vous ne souhaitez pas d'icône pour Git sur le bureau, vous pouvez décocher l'option "On the Desktop".
    Deuxième étape de l'installation de Git
    Pour cette deuxième étape on vous demande de choisir l'éditeur de texte associé à Git. Je vous conseille ici de choisir votre éditeur de texte habituel. L'éditeur proposé par défaut, Vim, peut s'avérer pratique en ligne de commande, mais vous serez certainement comme moi plus à l'aise avec Visual Studio Code ou un équivalent.
    Troisième étape de l'installation de Git
    On vous demande ici le nom de la branche par défaut pour les nouveaux projets Git. Par défaut, et historiquement, il s'agit de master. En revanche certaines équipes et certains services, dont Github, préfèrent appeler cette branche main. Vous pouvez donc choisir ce qui vous convient le mieux. Aucun choix ne sera bloquant de toute façon. Si vous ne savez pas quoi choisir, vous pouvez laisser l'option par défaut, "Lest Git decide".
    Quatrième étape de l'installation de Git
    Cette quatrième étape consiste à choisir où vous souhaitez pouvoir utiliser Git. Je vous conseille de choisir l'option du milieu ici : "Git from the command line and also from 3rd-party software".
    Cinquième étape de l'installation de Git
    Vous devez ici choisir la librairie utilisée par Git pour les connexions sécurisées. Je vous conseille de laisser OpenSSl.
    Sixième étape de l'installation de Git
    Sixième étape : vous devez faire un choix concernant la façon dont Git va gérer les sauts de lignes dans vos fichiers. Ces derniers étant différents sur Windows et Linux, il est important que tous les participants au projet utilisent le même format au moment où ils sauvegardent leur travail dans un commit. On sauvegarde donc généralement nos commits avec le format de sauts de ligne propre à Linux. Comme vous travaillez sur Windows, Git va devoir convertir les caractères de saut de ligne avant chaque commit. Je vous recommande donc, là aussi, de laisser le choix par défaut : "Checkout Windows-style, commit Unix-style line endings".
    Septième étape de l'installation de Git
    Il vous faut ensuite choisir le terminal que vous souahitez utiliser par défaut avec Git Bash. Ce dernier n'est en effet pas un vrai terminal lui-même, il utilise MinTTY qui est un émulateur de terminal Linux. Afin de suivre la suite de ce cours, notamment le module suivant, il est important que vous conserviez cette première option : "Use MinTTY (the default terminal of MSYS2)".
    Huitième étape de l'installation de Git
    Ensuite, choisir le comportement de la commande git pull, que nous verrons dans le module 6. Je vous recommande une fois de plus de conserver l'option par défaut ici : "Default (fast-forward or merge)"
    Neuvième étape de l'installation de Git
    Il vous faut maintenant choisir l'outil que Git utilise pour gérer vos connexions aux services distants (Github, Gitlab, Bitbucket, etc). Laissez encore l'option par défaut ici : "Git Credential Manager Core".
    Dixième étape de l'installation de Git
    On y est presque ! Laissez là aussi les options par défaut.
    Onzième étape de l'installation de Git
    Enfin, dernière étape ! Et toujours aucun suspense : laissez par défaut (donc ne cochez pas la case).

    Après ce calvaire consistant à cliquer une douzaine de fois sur le bouton "Next", nous voilà prêts : Git est installé sur votre machine !

    Nous en resterons donc là pour aujourd'hui, et poursuivrons la prochaine fois avec une initiation à la ligne de commande.

    L'installation de Git est terminée
    Git est installé ! Nous sommes maintenant prêts à nous confronter à la console

  • Comprendre la spécificité CSS

    Ou enfin comprendre pourquoi ce langage n'en fait qu'à sa tête


    Sommaire

    1. Introduction
    2. Le problème observable
    3. Les règles du jeu
    4. Le vrai problème : la maintenabilité
    5. Une première partie de la solution : le specificity graph
    6. L'autre partie de la solution : simplifier nos sélecteurs
    7. Conclusion : de la méthode et des bonnes pratiques

    1 - Introduction

    La spécificité fait partie des deux notions les plus importantes du langage CSS, l'autre étant évidemment la fameuse cascade.

    La compréhension de cette spécificité est essentielle à une bonne maîtrise du langage, et fait à l'heure actuelle défaut à trop de développeurs pourtant expérimentés. La raison : cette notion n'est que trop rarement abordée dans les cours/tutos/livres/formations sur CSS. Quand elle l'est, c'est souvent de façon beaucoup trop concise, imprécise voire inexacte.

    Évidemment il existe sur le web quantité de ressources directement consacrées à la spécificité. Il est possible de trouver quantité de tutos, articles, vidéos et packages dédiés à cela. Mais ce sont généralement des ressources qui sont spécifiquement dédiées à la spécificité. Cela représente un apprentissage supplémentaire à celui du langage étant donné que la notion est trop souvent absente des cours pour débutants ou des livres traitant de l'ensemble du langage. Et pourtant cette notion est si importante qu'elle devrait faire partie de tous les programmes d'apprentissage de CSS. C'est le problème que j'essaye de contribuer à solutionner en incluant cette notion dans mes cours, en insistant dessus.

    C'est aussi ce que je tente de faire ici en improvisant ce tuto.

    2 - Le problème observable

    Lorsqu'on apprend CSS, on apprend en général qu'en cas de conflits entre deux déclarations de propriétés, c'est celle écrite dans la règle la plus bas dans le code CSS qui "gagne".

    Pour illustrer, considérons le code HTML suivant :

    <header class="header-big"></header>
    Puis le CSS suivant :
    header {
        font-size: 20px;
    }
    
    .header-big {
        font-size: 24px;
    }

    Nous avons ici deux règles de CSS différentes qui vont toutes les deux s'appliquer à notre balise <header>.

    La première règle a pour sélecteur header soit le nom de la balise. Ce sélecteur signifie exactement "toutes les balises

    de la page". Il s'appliquera donc par défaut chaque fois que cette balise sera utilisée.

    La deuxième règle a pour sélecteur .header-big soit le nom d'une classe associée à la balise. Ce sélecteur signifie exactement "toutes les balises qui ont la classe header-big". Il s'appliquera donc par défaut sur toutes les balises possédant cette classe.

    Ces deux règles s'appliquent ici à la même balise HTML, et déclarent toutes les deux la propriété font-size. On est donc face à un conflit. Comme dit plus haut : c'est la règle écrite la plus bas qui gagne.

    Donc le texte aura ici une taille de 24px, telle que définie dans la deuxième règle.

    Jusqu'ici tout va bien.

    Le problème survient lorsque l'on inverse l'ordre des deux règles :

    .header-big {
        font-size: 24px;
    }
    
    header {
        font-size: 20px;
    }

    Ici on s'attend à ce que, comme précédemment, la règle écrite la plus bas soit prioritaire. Et donc à ce que le texte ait une taille de 20px. Mais non.

    Le texte fait toujours 24px.

    Nous avons inversé l'ordre des deux règles et pourtant c'est toujours la règle avec le sélecteur .header-big qui l'emporte.

    Qu\'est-ce donc cette diablerie
    C'est la fameuse spécificité qui provoque ce comportement.

    3 - Les règles du jeu

    La spécificité CSS, c'est la spécificité de vos sélecteurs. C'est, si vous préférez, leur complexité. Plus un sélecteur est considéré comme spécifique (donc complexe) plus il sera prioritaire sur les autres en cas de conflit.

    On peut donc observer via notre exemple précédent que le sélecteur .header-big est considéré comme plus spécifique que le sélecteur header. Et donc en déduire qu'en CSS les classes sont plus spécifiques que les noms de balises.

    Il existe un outil en ligne très pratique pour calculer la spécificité d'un sélecteur CSS, le Specificity Calculator

    Si on essaye d'entrer nos deux sélecteurs dedans, voici ce qu'on obtient :

    CSS Specificity Calculator - Résultat n°1
    Les valeurs de spécificité renvoyées par le calculator pour nos deux sélecteurs

    Le calculator nous renvoie des valeurs numériques correspondant à la spécificité de chacun des deux sélecteurs. Pour bien lire ces valeurs, il faut les lire un petit peu comme on lit des numéros de versions d'application :

    • le sélecteur .header-big a une spécificité qui vaut 0.1.0
    • le sélecteur header a une spécificité qui vaut 0.0.1

    Et on compare ces valeurs comme on comparerait des numéros de versions d'application, c'est à dire nombre par nombre : d'abord les deux premiers nombres entre eux (0 et 0), puis les deux seconds (1 et 0), puis les deux derniers (0 et 1).

    • On compare donc d'abord 0 et 0 : égalité
    • Puis on compare 1 et 0 : le premier sélecteur gagne
    • Pas besoin de comparer les derniers nombres, le premier sélecteur a déjà gagné

    Bon ok pour comparer deux valeurs entre elles, mais pour le calcul on va devoir utiliser ton lien à chaque fois ?

    Non. Uniquement lorsque vous aurez des sélecteurs trop complexes pour réussir à calculer la spécificité de tête. Dans un exemple comme le notre, il aurait été très facile de calculer cela nous-mêmes, sans passer par le site calculator. Il suffit de compter les occurrences des différentes parties de notre sélecteur : le nombre de balises, le nombre de classes, le nombre d'identifiants, etc. Cela fonctionne comme ceci :

    • Le premier nombre de la valeur de spécificité correspond au nombre d'identifiants. Ainsi le sélecteur #intro #title + #subtitle aura une valeur de spécificité de 3.0.0 ;
    • Le deuxième nombre de la valeur de spécificité correspond au nombre de classes ou pseudo-classes. Ainsi le sélecteur .special:hover aura une valeur de spécificité de 0.2.0 ;
    • Le troisième et dernier nombre de la valeur de spécificité correspond au nombre d'éléments (noms de balises) ou pseudo-éléments. Ainsi le sélecteur article p::before aura une valeur de spécificité de 0.0.3 ;

    Imaginons deux sélecteurs beaucoup plus complexes :

    CSS Specificity Calculator - Résultat n°2
    Ca se complique un peu...
    • Le premier possède 1 identifiant : #homepage ;
    • Le premier possède 2 classes : .viewport-mobile et .active ;
    • Le premier possède 1 pseudo-classe : :hover ;
    • Le premier possède 2 éléments : body et section ;

    => Le premier sélecteur a donc une valeur de spécificité égale à 1 . ( 2 + 1 ) . 2 = 1.3.2

    • Le second possède 0 identifiant ;
    • Le second possède 3 classes : .menu-navbar, .menu-link et .disabled ;
    • Le second possède 2 éléments : a et a ;
    • Le second possède 1 pseudo-élément : ::first-letter ;
    • La fonction :not() n'étant ni un identifiant, ni une classe, ni une pseudo-classe, ni un élément, ni un pseudo-élément, elle est ignorée dans le calcul de spécificité (elle compte pour 0 si vous préférez) ;

    => Le second sélecteur a donc une valeur de spécificité égale à 0 . 3 . ( 2 + 1 ) = 0.3.3

    Et donc si l'on souhaite les comparer, c'est le premier qui gagne. On compare d'abord le nombre d'identifiants : le premier sélecteur en a 1 et le second en a 0. Pas besoin de comparer la suite, le premier sélecteur a gagné.

    Ok, donc il faut savoir que les sélecteurs les plus spécifiques sont toujours prioritaires. Et qu'on peut calculer facilement la valeur de spécificité pour chaque sélecteur, soit de tête soit avec le site Specificity Calculator. C'est tout ?

    Non. Tout cela crée un problème supplémentaire : la difficulté de maintenir un code CSS sur le long terme.

    4 - Le vrai problème : la maintenabilité

    Jusqu'ici nous avons comparé deux règles entre elles. Facile d'oberver laquelle est prioritaire et d'adapter son code en conséquence. Maintenant imaginez dans un code CSS de plusieurs milliers de lignes, comprenant des centaines de sélecteurs dont certains très complexes (et donc très spécifiques). Imaginez que ce fichier soit celui d'un site en production, et qu'une équipe de plusieurs développeurs front maintienne ce fichier, chaque développeur de l'équipe étant susceptible d'intervenir dessus. C'est à dire de modifier ou rajouter du CSS parmi ces milliers de lignes déjà existantes.

    Il en résulte une grande difficulté à savoir où écrire son code pour qu'il fonctionne. Le réflexe de départ veut que toute nouvelle règle ajoutée vienne se placer à la suite du code existant, plus bas dans le fichier. Mais vous l'avez vu avec notre exemple plus haut : si une règle avec un sélecteur plus spécifique précède, alors la notre perdra les conflits éventuels.

    Cette situation est loin d'être rare. Tout projet un peu sérieux comprend très vite un code CSS assez conséquent, qui a tendance à s'allonger sur la durée. Cette frustration d'écrire un code CSS qui ne fonctionne pas du tout, TOUS les développeurs web front-end la connaissent. Elle est à l'origine de beaucoup de mépris envers le langage lui-même, de la part de gens n'ayant jamais compris/appris/entendu parler de la notion de spécificité. Et qui sont pourtant parfois d'excellents développeurs.

    Face à ce genre de cas, souvent mêlés à la nécessité de respecter les délais, on se retrouve la plupart du temps à appliquer l'une des deux méthodes suivantes, relevant davantage du "patch à l'arrache" que de la réelle solution :

    • On peut vouloir volontairement compliquer le sélecteur de notre nouvelle règle, pour être certain qu'il soit prioritaire. Rajouter plusieurs identifiants, classes, éléments, etc.
    • Ou on peut utiliser !important sur toutes les propriétés qui ne s'appliquent pas, pour forcer leur priorité.

    Dans un cas comme dans l'autre, ces solutions sont très mauvaises sur le long terme. Elles condamnent les développeurs du projet à les utiliser de plus en plus fréquemment. Jusqu'à ce qu'ils finissent avec un fichier bourré de sélecteurs beaucoup trop complexes inutilement et/ou de !important partout pour chaque propriété ou presque. Petit à petit, semaine après semaine, itération après itération, le fichier CSS lui-même se transforme en une dette technique longue de plusieurs milliers de lignes, de plus en plus impossible à réparer.

    Voilà exactement ce qui fait que CSS a la réputation d'être très difficile à maintenir sur le long terme. Ce qui fait que durant le cycle de vie d'un projet, on se retrouvera plusieurs fois à raser entièrement notre code CSS pour le recréer de zéro faute de pouvoir encore le faire évoluer.

    A titre d'exemple, le code CSS de Bootstrap utilise près de 1300 fois le mot-clé !important. C'est BEAUCOUP BEAUCOUP BEAUCOUP trop. Même dans un projet si conséquent que Bootstrap, !important ne devrait pas apparaître plus d'une dizaine de fois. Idéalement, il ne devrait pas du tout apparaître. Sur le long terme, le code de Bootstrap est condamné à être entièrement réécrit ou à devenir impossible à faire évoluer. Et pourtant Bootstrap n'est pas plus "mal fait" qu'un autre. Le projet est sérieux, les développeurs qui y contribuent sont tout à fait compétents. Le problème n'est pas Bootstrap. Bulma CSS l'utilise 504 fois. Foundation CSS l'utilise 59 fois, ce qui est déjà nettement mieux mais toujours trop. L'écrasante majorité des codes CSS du monde, y compris sur de très très gros sites web, fait face à la même situation.

    Parce que la notion de spécificité est trop souvent ignorée. Parce que les développeurs web de ma génération ne l'ont pas apprise lorsqu'ils débutaient, et ne l'ont découverte que trop tard (quand ils l'ont découverte).

    S'ils l'avaient apprise et comprise, ils auraient pu en déduire depuis bien longtemps les solutions et bonnes pratiques qui suivent.

    Ne faites pas comme nous à l'époque : n'ignorez pas cette notion. N'ignorez pas les bonnes pratiques qui suivent. Elles feront de vous quelqu'un avec une bien meilleure maîtrise de CSS que la majorité des "devs seniors" actuels.

    Que la Spécificité CSS soit avec vous
    Que la Spécificité CSS soit avec vous

    5 - Une première partie de la solution : le specificity graph

    Le specificity graph est une notion amenée par Harry Roberts (https://csswizardry.com/). Notion qui m'aura personnellement permis de comprendre l'importance de la spécificité, notamment via cette vidéo :

    Harry Roberts - Managing CSS Projects with ITCSS

    Le nom "ITCSS" qu'il donne à sa méthode n'est pas important ici. Pas plus que les catégories qu'il utilise dans son triangle inversé. C'est sa classification, vous pouvez en créer une qui vous soit propre.

    Ce qui est important en revanche c'est bien la notion de specificity graph.

    L'idée c'est de faire une représentation en graphique de la spécificité de chacun de vos sélecteurs, rapportée à leur position au sein de votre code CSS.

    Sur les screens ci-dessous (issus du site d'Harry Roberts), on place en ordonnées le niveau de spécificité de nos sélecteurs, et en abscisses leur position dans le code. Plus c'est haut plus c'est spécifique, plus c'est à droite plus c'est écrit "en bas" du code CSS.

    CSS Specificity Graph - Courbe n°1
    Un specificity graph en dents de scie est mauvais signe

    Ici nous avons l'exemple d'un mauvais specificity graph. Tout est désordonné : vous avez d'abord des règles peu spécifiques, puis des un peu plus spécifiques, puis des très peu spécifiques, puis des très très spécifiques... Et ça continue en dents de scie comme ça. C'est exactement le genre de code CSS que je décrivais plus haut, qui va nous forcer à utiliser des !important partout.

    C'est exactement le genre de code CSS qui devrait être réordonné dans l'ordre de spécificité.

    A titre de comparaison, voici un bon specificity graph, celui d'un fichier bien fait, dans lequel les règles sont écrites dans l'ordre de spécificité de leurs sélecteurs :

    CSS Specificity Graph - Courbe n°2
    Voilà une belle courbe 😊

    Dans un fichier comme celui-ci, il n'y a PAS BESOIN d'utiliser !important. Sauf besoins trop spécifiques pour les détailler ici, vous pouvez vous en sortir sans écrire !important une seule fois. Et ce même si votre fichier CSS est très long.

    Dans un fichier comme celui-ci, tout code CSS qui devra être ajouté durant le cycle de vie du projet pourra être ajouté au bon endroit, en respectant l'ordre de spécificité. Ce qui nous garantit que tout code CSS ajouté au bon endroit va fonctionner du premier coup.

    => La première leçon que l'on peut tirer de tout ceci, la première bonne pratique, c'est de toujours ordonner vos règles CSS selon l'ordre de spécificité de leur sélecteurs.

    => Par extension, une seconde bonne pratique peut être d'inscrire la valeur de spécificité dans un commentaire au-dessus de chaque sélecteur.

    En réécrivant notre code de départ selon ces deux principes, ça nous donnerait ceci :

    /* Specificity : 0.0.1 */
    header {
        font-size: 20px;
    }
    
    /* Specificity : 0.1.0 */
    .header-big {
        font-size: 24px;
    }

    On obtient ainsi un code beaucoup plus logique : ce qui est en bas est toujours prioritaire sur ce qui est en haut. La présence des commentaires aide à vérifier cela d'un simple coup d'oeil, nous permettant de savoir très facilement où ajouter du code.

    Par exemple, imaginons que l'on veuille rajouter une règle avec pour sélecteur article header. On peut déjà calculer que, puisque ce sélecteur contient 2 éléments, sa valeur de spécificité est de 0.0.2. Ajouter cette règle à notre code au bon endroit donnerait donc ceci :

    /* Specificity : 0.0.1 */
    header {
        font-size: 20px;
    }
    
    /* Specificity : 0.0.2 */
    article header {
        font-size: 24px;
    }
    
    /* Specificity : 0.1.0 */
    .header-big {
        font-size: 24px;
    }

    Nous avons su faire évoluer notre code facilement et rapidement, en gérant nos conflits dans un ordre logique, tout en conservant un specificity graph qui soit propre.

    6 - L'autre partie de la solution : simplifier nos sélecteurs

    Afin de nous simplifier la tâche d'avoir à calculer des valeurs de spécificité et d'ordonner nos règles, quelques bonnes pratiques supplémentaires peuvent aider. Elles visent presque toutes le même objectif : simplifier nos sélecteurs au maximum.

    En premier les identifiants. Ils font la même chose que les classes, sauf qu'on est obligés de les utiliser une seule fois côté HTML. Les classes n'ont pas cet inconvénient. Selon tout ce que l'on vient de découvrir ensemble, ils ont également un autre inconvénient : ils sont plus spécifiques que les classes, les noms de balises, les pseudo-classes et les pseudo-éléments. Ils sont toujours prioritaires sur tout ça. Ce qui nous force à les écrire à la fin de notre code CSS, afin qu'ils soient à l'extrême en abscisses et en ordonnées sur la courbe de notre specificity graph (tout en haut à droite). Cette méthode règle certes les problèmes éventuels, respecte les bonnes pratiques énoncées précédemment... Mais on peut se simplifier la vie encore plus. Il suffit de ne plus du tout utiliser d'identifiant en CSS. On peut toujours s'en servir en HTML (notamment pour créer des ancres ou relier des balises de formulaires à l'atribut for des labels). Mais on arrête complètement de les utiliser côté CSS. On peut s'en passer car tout ce qui est faisable avec est faisable avec les classes. Ne plus du tout utiliser d'identifiant nous permet d'avoir un specificity graph moins complexe, des différences moins grandes entre nos différents sélecteurs. Et donc un code plus simple à ordonner. Et donc à maintenir sur le long terme.

    Ensuite, les sélecteurs du DOM : le   (l'espace), le >, le ~ et le +. Dans la majorité des cas, ces sélecteurs peuvent être simplifiés en les remplaçant par la création d'une nouvelle classe. Ce qui impose évidemment de modifier le HTML pour attribuer cette nouvelle classe aux balises concernées. Cela représente un petit effort entièrement justifié par la compensation : là encore on va simplifier grandement notre specificity graph, là encore on va avoir moins de différences entre nos sélecteurs. On "réduit les inégalités" entre nos règles CSS. Et réduire les inégalités ça fait toujours du bien. Là aussi notre code sera plus simple à ordonner, et donc à maintenir sur le long terme.

    Ensuite, les styles inline. C'est à dire les styles écrits côté HTML, directement sur les balises à l'aide de l'attribut style. Par exemple : <header style="font-size:16px"></header>. Ces déclarations sont prioritaires sur tout (sauf !important) : les identifiants, les classes et pseudo-classes, les éléments et pseudo-éléments. Pour des raisons évidentes on va préférer éviter au maximum le recours à ces styles inline. C'est de toute façon une façon très limitée d'écrire du CSS, donc on ne perd pas grand chose à s'en servir le moins possible.

    Enfin le fameux !important. Vous l'avez maintenant compris il est prioritaire sur TOUT le reste : les styles inline, les identifiants, les classes et pseudo-classes, les éléments et pseudo-éléments. C'est le joker par excellence. Mais c'est aussi très dangereux d'avoir recours à cette méthode, pour les raisons expliquées plus haut. C'est mettre un pied dans l'engrenage consistant à l'utiliser de plus en plus souvent, jusqu'à ne plus pouvoir s'en passer. La règle à retenir est donc de ne JAMAIS utiliser !important.

    Dernier détail, les règles groupées avec , : elles comptent bien comme plusieurs règles de CSS, avec chacune son sélecteur et donc sa spécificité. Par exemple, on aurait pu réécrire nos règles précédentes comme ceci :

    /* Specificity : 0.0.1 */
    header {
        font-size: 20px;
    }
    
    /* Specificity : 0.0.2, 0.1.0 */
    article header, .header-big {
        font-size: 24px;
    }

    La dernière règle est une règle groupée, c'est en fait deux règles en une. On a donc bien deux valeurs de spécificité différentes ici, qui pourront toutes les deux être utilisées par le navigateur pour effectuer des calculs de priorité selon les conflits rencontrés. C'est à dire que même si l'on a groupé deux de nos règles, le sélecteur header peut toujours rentrer en conflit avec article header et/ou avec .header-big.

    Pour ordonner correctement vos règles, vous placerez donc celles qui sont groupées selon la valeur de spécificité la plus forte parmi tous les sélecteurs qu'elles contiennent. Dans notre exemple, pour savoir où placer notre règle groupée, on tient compte du 0.1.0 et non du 0.0.2.

    7 - Conclusion : de la méthode et des bonnes pratiques

    En résumé, la spécificité CSS est une valeur calculable, qui est utilisée par le navigateur pour déterminer la priorité des déclarations en cas de conflit.

    Les règles de priorité fonctionnent comme ceci :

    • Toute propriété possédant !important sera prioritaire sur tout le reste ;
    • Ensuite toute déclaration inline sera prioritaire ;
    • Ensuite c'est le sélecteur avec le plus grand nombre d'identifiants qui sera prioritaire ;
    • Ensuite c'est le sélecteur avec le plus grand nombre de classes ou pseudo-classes qui sera prioritaire ;
    • Ensuite c'est le sélecteur avec le plus grand nombre d'éléments ou pseudo-éléments qui sera prioritaire ;
    • Et enfin c'est les règles écrites en dernier qui seront prioritaires sur celles écrites en premier.

    En conclusion, on en déduit les bonnes pratiques suivantes :

    • Toujours ordonner vos règles CSS selon l'ordre de spécificité de leur sélecteurs
    • Inscrire la valeur de spécificité dans un commentaire au-dessus de chaque sélecteur
    • Ne plus utiliser d'identifiants dans vos sélecteurs CSS
    • Dès que possible, remplacer les sélecteurs trop complexes par la création de nouvelles classes
    • Dès que possible remplacer les sélecteurs du DOM (  > ~ +) par la création de nouvelles classes
    • Éviter au maximum l'utilisation de styles inline
    • Ne JAMAIS utiliser !important
    • Si vraiment vous êtes obligé d'utiliser !important : placez les règles qui s'en servent à la fin de votre code, en dernier

    Mais ta solution là, ça va pas nous faire créer trop de classes ?

    Elle va vous en faire créer beaucoup plus qu'avant oui. Mais pas trop. Les navigateurs savent gérer, même avec un nombre de classes très conséquent, faites-leur confiance. En contrepartie vous produisez un code CSS qui a tout pour évoluer de façon propre, être toujours maintenable d'ici plusieurs années malgré beaucoup d'ajouts et de modifications, capable d'encaisser des montées en charge, capable d'être maintenu par plusieurs développeurs s'ils respectent tous les mêmes bonnes pratiques.

    Enfin on pourrait rajouter à tout ceci quelques bonnes pratiques plus génériques et évidentes :

    • Que vous préfériez une approche par composants ou une approche plus fonctionnelle à la Tailwind, choisissez une syntaxe pour vos classes et respectez-la. Vous pouvez vous inspirer de ce qui existe : BEM, Atomic Design, etc
    • De façon plus générale faites preuve de logique pour nommer vos classes, pensez-les comme les plus descriptives et réutilisables possible
    • Utilisez un préfixe par projet commun à toutes vos classes, ex: masta_header, masta_button, etc. Cela vous évitera les conflits avec le CSS des différentes librairies que vous voudrez utiliser
    • Placez vos @font-face et vos @keyframe en tout début de fichier
    • Placez vos @media en toute fin de fichier, et à l'intérieur appliquez de nouveau un tri de vos règles par valeur de spécificité

    Avec tout ça, vous avez tout ce qu'il vous faut pour écrire le code CSS le plus propre et maintenable qui soit. A vous ensuite d'avoir rigueur et méthode afin d'appliquer ces bonnes pratiques sur tous vos projets.

    Par expérience, je l'ai fait, testé en production, ça fonctionne, ça change tout. Depuis que j'ai compris tout ça, je sens que je maîtrise CSS bien mieux qu'avant, ce qui a fait ses preuves dans la plupart de mes projets. J'espère que ce sera également votre cas dès à présent 😎

    Tim Berners-Lee l'inventeur du Web
    Grâce à ce tuto Tim maîtrise le web à la perfection