Dans le monde de la tech, Git est quasi indispensable. Aujourd’hui ARCA vous dit tout ce qu’il y a à savoir sur cet outil !
#1 Git, kézako ?
Git est un outil de gestion des versions (Version Control System, ou VCS), créé par Linus Torvalds (le père fondateur du noyau Linux) en 2005, et distribué en licence libre. Des VCS, il en existe plusieurs, parmi les plus répandus Mercurial, Subversion et bien sûr Git. Mais, c’est quoi au final un VCS ?
Le but d’un VCS est de garder en mémoire toutes les modifications apportées à un système de fichiers (un dossier et tous ses sous-dossiers) au court du temps. Non seulement la dernière version mais aussi toutes les étapes, dans l’ordre, qui y ont conduit. Il est très largement utilisé dans les projets informatiques, mais peut très bien être utilisé dans d’autres contextes, comme par exemple garder les modifications d’un article en cours de rédaction !
Pour pouvoir gérer ces versions, le VCS ne va pas sauvegarder l’ensemble du projet, mais uniquement les modifications, ligne par ligne. Ce qui nous amène au second but d’un VCS : partager un projet. Imaginez une équipe travaillant sur un même projet. Tant que chacun travaille sur un fichier différent, on peut facilement remplacer les fichiers en question. Mais si plusieurs personnes travaillent sur le même fichier, mais pas forcément au même endroit (disons, l’introduction d’un article et sa conclusion), le dernier à sauvegarder doit d’abord intégrer les modifications du premier sous peine de les écraser. Un VCS solutionne ce problème, puisqu’il saura qui a fait quelle modification et dans quel ordre.
#2 Terminologie
Un projet git amène son lot de vocabulaire propre. Petit tour d’horizon des mots incontournables.
Repository : c’est le dossier racine du projet que l’on souhaite versionner. Il représente l’état du projet depuis les dernières modifications. Il constitue aussi le commit tree (arbre de commits).
HEAD : pointeur dans l’arbre de commits. Souvent, il sera sur le dernier commit de la branche courante, mais il peut pointer sur une version antérieure (on parle alors de mode détaché).
Working directory : littéralement « dossier de travail », c’est la version locale en cours (là où sont faites les modifications).
Staging : la liste des modifications qui sont prêtes à être sauvegardées.
Stash : Un genre de staging alternatif, qui permet de sauvegarder des modifications sans les commiter dans le repository.
Commit : ensemble de modifications, qui représente une version sauvegardée. On cherchera à faire des commits les plus petits possibles (dits « atomiques »), et que chaque commit porte une information précise (mettre à jour les données d’utilisateurs, ajouter une page, etc.).
Branche : une branche représente une divergence à partir d’un commit donné. Le but de « partir en branche » est de travailler sur une copie propre lorsque des modifications importantes sont à venir et ramener (merger) la branche quand tout est fini.
Conflit : parfois lorsqu’on récupère du code distant (voir partie suivante), git n’arrive pas à déterminer l’ordre des modifications à appliquer. Dans ce cas, il note les deux parties en conflit, et attend une intervention humaine pour résoudre les conflits et continuer. Cela arrive souvent lorsque le même fichier a été modifié de manière différente au même endroit.
Merge : c’est le fait de joindre deux parties de codes qui ont divergé. Cela arrive à chaque fois qu’on tire du code depuis un repository distant, ou lorsqu’on veut merger deux branches l’une dans l’autre.
#3 Repository distant (remote server) et hébergeurs
Dans la partie #1, nous avons abordé le fait de pouvoir partager un repository. Pour cela, Git (comme d’autres VCS) permet aussi la gestion de repository distant : les modifications sont poussées sur un site, afin que toutes les personnes (autorisées) accèdent aux changements en temps réel. Il existe donc des hébergeurs spécialisés git, parmi lesquels GitLab, GitHub, et BitBucket. Chacun a ses spécificités, ses avantages et ses inconvénients. À l’heure actuelle, GitHub est la plateforme de référence pour les développeurs avec plus de 40 millions d’utilisateurs, devant Bitbucket (plus de 10 millions). GitLab proposant d’autohéberger ses instances, il est plus dur d’obtenir des chiffres.
#4 Cheatsheet : les commandes à retenir
La principale interaction avec Git se fait en ligne de commande, via le logiciel git. De nombreux logiciels visuels permettent de ne pas utiliser la ligne de commande, mais connaitre la commande et ses actions permet d’utiliser une interface, l’inverse n’est pas vrai ! La liste peut paraître longue, mais l’usage de la plupart des commandes est similaire.
git init
: permet d’initialiser un repository dans le dossier où l’on se trouve. Par défaut, la branche est master, mais on peut le changer par la suite.git add
: permet d’ajouter le fichier dans le staging. Le raccourcigit add .
rajoute tout ce qui est présent dans le dossier (et qui a été modifié).git commit
: crée un nouveau commit. Un éditeur va s’ouvrir pour permettre d’écrire un message de commit ou on peut l’écrire directement avec le flag-m
.git stash
: comme git commit, mais dans la liste de stash. Attention, sans la commandegit stash save
, le message sera « wip on <branche>… ».git stash list
: affiche la liste des versions « stashées ».git stash pop
: ressort une entrée du stash dans le working directory. On peut préciser l’index à appliquer, par défaut la dernière.git stash apply
: comme pop, mais ne supprime pas l’entrée de la liste de stash. On peut aussi préciser l’index.git stash drop
: supprime l’entrée mais ne la réinstalle pas dans le working directory. On peut là encore préciser l’index.git checkout
: change de branche. Le flag-b
permet de créer la branche si elle n’existe pas.git status
: montre les différences entre le working directory, le staging, et le repository local. Si une commande est en cours (git merge, git rebase,… ), cette commande montre aussi des indications sur la suite de la manœuvre.git log
: montre tous les commits dans l’ordre anti-chronologique (le dernier est en haut de la liste).git hist
: un alias de git log avec moins de détails.git set origin
: permet de dire au repository local sur quelle adresse aller chercher les modifications distantes.git remote
: ensemble de commandes pour gérer les repositories distants. Le flag-v
permet d’afficher toute la liste.git fetch
: permet de récupérer toutes les modifications distantes sans les ajouter au working directory (git aura connaissance de leur existence, et c’est tout).git pull
: comme fetch, mais intègre les modifications.git push
: envoie le(s) commit(s) sur le repository distant. Le flag--set-upstream
permet de définir la branche distante. Il est obligatoire si la branche distante n’existe pas encore dans le repository distant, et git vous le dira.git merge
: inclut tous les changements d’une branche ou d’une ressource distante dans la branche courante. Peut générer des conflits.git rebase
: permet de réécrire l’historique des commits. il permet de mettre à jour une branche sur une autre (comme si au lieu de démarrer au commit A, elle commençait à partir du commit B), ou de manière interactive (avec le flag-i
) permet de réduire plusieurs commits les uns dans les autres (« squash »).git cherry-pick
: permet de prendre n’importe quel commit, n’importe où, et de le rajouter dans la branche courante en le copiant, sans devoir merger tout le reste.
Une dernière commande, un peu particulière mais qui vous sauvera peut-être la vie, git bisect
. C’est un utilitaire magique : si vous rencontrez un bug ou une chose qui est mal faite, et que vous voulez savoir ce qui c’est passé (quand et comment ce bug est arrivé), il suffit de donner un commit dont vous êtes sûr(e)s que tout fonctionnait. A partir de là, git choisit lui-même un certain nombre de commits, et va vous demander à chaque étape de dire si c’est bon ou si c’est mauvais (littéralement: git bisect [good|bad]
), jusqu’à trouver le commit ayant introduit l’anomalie, vous permettant d’agir sur le code responsable.
Enfin, cette liste est loin d’être exhaustive, mais représente ce que nous considérons comme indispensable chez ARCA. Git permet encore bien plus de choses, et le flag --help
est toujours là pour vous guider si vous avez un doute.
Le petit bonus du jour, un alias « git lg » bien utile :
"log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
#5 Pour aller plus loin : les fichiers spécifiques et les hooks
En plus des commandes vues précédemment, git apporte des options de configuration propres à chaque repository.
Le fichier .gitignore, par exemple, permet de dire à git d’ignorer une liste de dossiers et de fichiers qu’il ne faudra jamais commiter. On ajoute généralement dans ce fichier les fichiers générés, les fichiers de configuration qui dépendent de chacun, etc. Forcément, ce fichier dépend des technologies utilisées (langage, IDE,… ), et nous vous conseillons le très bon site gitignore.io qui vous permettra de générer le fichier pour vos besoins.
Le fichier .gitattributes permet de partager des configurations entre toutes les personnes du projet, comme par exemple les retours à la ligne (différent entre Unix et Windows) qui sinon polluent les commits: le changement d’un retour à la ligne n’est pas un changement critique qui doit apparaître dans l’arbre.
Git permet aussi de définir des hooks (que vous trouverez dans le dossier .git/hooks/ du projet), qui sont des scripts qui vont être joués à différents moments du cycle de vie git. Le hook pre-commit, par exemple, permet d’intercepter le commit et d’ajouter des évènements (mettre à jour une version, vérifier les tests,… ) avant de sauvegarder le commit. Pour plus d’informations, il suffit de regarder les fichiers déjà présents dans le dossiers .git/hooks/, qui se terminent en .sample (fichiers d’exemples ignorés). Si la commande retourne une erreur, l’évènement en cours est arrêté (par exemple, le commit est annulé). Attention, git se repose sur le nom des fichiers, ne les modifiez pas !
Bien entendu, pour toutes vos questions, Git propose une documentation très complète pour aller plus loin.