Git Memorandum

Comme pour tous.tes les développeur.ses, Git fait partie de mon quotidien… Et comme tous.tes les développeur.ses, il m’arrive aussi de galérer avec Git 😦 .

C’est pourquoi j’ai décidé de créer ce billet de blog « Aide mémoire », destiné aussi bien aux débutant.es qu’au utilisateur.ices averti.es… Article sur lequel je partagerai bien entendu mes petites galères et mes (grandes) solutions !

Sauf notification contraire, les illustrations et schémas sont soit personnelles, soit issus de la documentation officielle : https://git-scm.com/doc. Mes sources sont principalement la doc officielle de Git, mes expériences perso, un super meetup organisé par le Tours JUG : http://www.toursjug.org, et un petit guide créé par Samuel Dauzon et édité par les éditions Eni : https://www.editions-eni.fr/supports-de-cours/livre/git-aide-memoire-pour-une-utilisation-au-quotidien.

Les Branches et les commits

Là, c’est la base et surtout la force de Git. Nous manipulons les branches quotidiennement.

Dans l’exemple ci-dessus, extrait de la documentation officielle, nous avons 3 branches : « master », « develop » et « topic ». Master est la branche par défaut de Git, et généralement la branche de la version de production. C1, C2… sont des « commits« . Ici, le commit C1 à été effectué dans la branche « master », C2 à C5 dans la branche « develop », et C6, C7 dans « topic ».

L’index de Git

Quand un.e développeur.se souhaite enregistrer son travail dans Git, il.elle effectue un commit qui contiendra les modification à ajouter au projet. Avant d’être intégrées dans un commit, les modifications passent obligatoirement dans l’index. L’index est une zone d’attente avant commit. Il est possible d’ajouter les modification d’un fichier à l’index via la commande git add.

Les références

Etant donné que l’identifiant d’un commit est un hash de 40 caractères hexadécimaux, Git propose de travailler à partir de références. Les références sont des noms qui pointent sur des commits. Les tags sont des références statiques : un tag est immuable, il pointera toujours sur un commit précis. Les branches sont des références dynamiques : chaque nouveau commit dans une branche entraîne une modification de la référence qui pointe vers le nouveau commit. Une référence centrale de Git est HEAD. Elle pointe vers le commit qui sert de base de travail. En d’autres termes, c’est le commit sur lequel le.a développeur.se est placé.e.

Fusionner ou rebaser ?

Les utilisateur.ices de Git hésitent souvent entre 2 méthodes d’intégration des modifications d’une branche dans une autre : effectuer une fusion ou un rebase. Le but des 2 méthodes est le même : intégrer les modifications d’une branche dans une autre branche, seule la forme change; La fusion regroupe toutes les modifications dans un commit appelé commit de merge. Le rebase va ajouter les comités de la branche dans la branche de destination avant leur leur divergence.

Fusion : le commit M est le commit de merge qui regroupe les modification de C3 et C4

Rebase : le commit C4 est inséré à la suite de C2, l’ancêtre commun des 2 branches

L’avantage principal de la fusion est qu’il n’y a pas de ré-écriture d’historique. Cela améliore la fiabilité d’un dépôt partagé entre plusieurs développeur.ses, car partager des historiques ré-écrits poserait des problèmes. Si les messages de commit sont explicites et clairs, le dépôt garde une réelle cohérence.

L’avantage principal du rebase est qu’il n’y a pas de commit de merge. En effet, dans de nombreux projets, les commits de merge polluent l’historique car leur message se résume souvent à « merge », ce qui nuit à la lisibilité. Les commits de merge présentent l’inconvénient de résumer un certain nombre de commits dans un seul commit, ce qui nuit à son aspect unitaire.

Dépot central et dépôt distant

L’intérêt de Git est de permettre à plusieurs développeur.ses de travailler sur le même projet. Chaque développeur.se possède son propre dépôt, lié à un dépôt central commun à toute l’équipe. Ainsi, chacun peut envoyer au dépôt distant les comités qu’il a effectués dans son dépôt local, et récupérer le travail effectué par les autres développeur.ses.

Obtenir de l’aide

Pour afficher l’aide générale de Git, il y a le site web : https://git-scm.com/doc, mais aussi la commande git –help. Pour afficher l’aide spécifique d’une commande, il faut utiliser la syntaxe : git commande –help.

Créer un dépôt (git init)

Dans le dossier du projet, saisir la commande git init. Attention, cette commande ne clone pas un dépôt existant, mais crée un dépôt vierge de tout commit.

Configurer un dépôt (git config)

Après l’installation de Git, il est nécessaire de définir certains éléments, comme les prénoms, noms et adresses email des utilisateur.ices. La syntaxe permettant de configurer un élément est : git config clé valeur.

ex : git config –global user.name « Vincent Barousse »

Il existe 3 niveaux de configuration : system, global et local.

L’argument –edit permet d’ouvrir un éditeur de texte pour éditer la configuration.

Visualiser les fichiers modifiés (git Status)

Avant de commiter, il vaut toujours mieux jeter oeil sur les fichiers qui ont été modifiés. Cela peut être pratique si certains fichiers non désirés se sont glissés dans le dépôt durant le développement. Pour afficher les fichiers ajoutés, modifiés ou supprimés, il faut utiliser la commande git status. Cette commande affiche les fichiers prêts à être commités (donc présents dans l’index), et ceux qui sont dans le répertoire de travail.

Préparer un commit (git add)

L’index de Git est une zone d’attente de modifications avant un commit. C’est à dire que les modifications doivent êtres placées dans l’index avant de commiter. Pour ajouter les modifications d’un fichier à l’index, on utilise la commande git add chemin/fichier.ext. L’argument –all permet d’ajouter toutes les modifications. Souvent, cet argument nécessite d’avoir un fichier .gitignore complet pour ne pas ajouter de modifications non désirées.

Commiter (git commit)

La notion du moment de commiter est primordiale. Un commit doit représenter un ensemble cohérent de modifications. Cela peut être le correctif d’un bug, l’ajout d’une petite fonctionnalité,… Il est déconseillé d’effectuer des commits de plus de 200 lignes de modifications.

Le commit sert à enregistrer les modifications du projet. Lors d’un commit, Git récupère les modifications dans l’index et les enregistre dans un commit. Pour commiter, il faut utiliser la commande git commit. Cette commande affiche un éditeur de texte permettant de saisir un message de commit. Ce dernier est composé d’un titre de 49 caractères maximum et d’éventuels commentaires.

Il est nécessaire d’écrire un très bon message de commit, car il sera lu des dizaines ou des centaines de fois. Il doit être le plus clair possible. Um message de commit se présente sous la forme contexte: mots clé représentatif. Par exemple : Boutique: affichage en dollars et en euros.

L’argument -m « titre du commit » permet de définir directement le titre, l’argument –all effectue un git add –all avant de commiter. L’argument –amend remplace le dernier commit par le nouveau commit. A ne pas utiliser si le commit à été partagé sur d’autres dépôts.

Déplacer ou renommer un fichier (git mv)

Pour déplacer ou renommer un fichier, on utilise la syntaxe : git mv chemin/origine.ext chemin/destination.ext.

Supprimer un fichier (git rm)

La commande rm de Git permettant de supprimer un fichier les place en réalité dans la zone d’index, afin que la suppression soit effective dans le prochain commit. La syntaxe est : git rm chemin/fichier.ext.

Ignorer les fichiers avec .gitignore

Certains fichiers d’un projet ne doivent pas êtres versionés (fichiers de configuration, fichiers temporaires…). Pour cela, on place une liste de fichier à ignorer dans un fichier nommé .gitignore situé à la racine du projet. Plus d’infos ici : https://git-scm.com/docs/gitignore

Consulter l’historique (git log)

Permet de retrouver un ou des commits précis pour en supprimer ou consulter les données qui y sont liées (modifications, messages de commit, auteur.es…). la commande est git log.

Ses arguments fréquents sont :

  • –folow : permet de suivre les fichiers renommés / déplacés
  • –nb où nb est un entier positif : limite le nombre de commits affichés
  • –after=date ou –before=date : affiche les commits avant ou après une date définie au format AAAA-MM-JJ
  • –grep= »patron » : permet de rechercher un patron dans les messages de commit
  • –no-merges : permet d’ignorer les commits issus de fusions
  • –oneline : permet d’afficher un seul commit par ligne
  • -S « chaîne à rechercher » : permet de rechercher des commits dont les modifications contiennent la chaîne
  • nom-de-branche.. : permet de lister les commits d’une branche. Attention, la syntaxe est composée du nom de la branche suivie de deux points

Consulter les modifications (git diff)

Le modifications peuvent êtres listées avec la commande git diff, qui affiche les différences entre le répertoire de travail et l’index.

Ses arguments fréquents sont :

  • git diff –cached : affiche la différence entre l’index et le HEAD
  • git diff HEAD : affiche la différence entre le dernier commit et le répertoire de travail
  • git diff commit1 commit2 : affiche la différence entre 2 commits

Nommer un commit (git tag)

La méthode git-flow est une méthode de gestion des branches. Elle propose que la branche master soit la branche contenant toutes les versions dessinées à la production. Chaque commit de la branche master est donc destiné à devenir une version de production et doit donc posséder un numéro de version. Les tags permettent de facilement donner un numéro de version à un commit.

Pour cela, il faut se placer sur le commit, puis utiliser la commande git tag nom-à-donner.

On peut également utiliser la commande git tag nom-à-donner hash-du-commit, qui permet de ne pas avoir à se positionner sur le commit.

Les arguments les plus fréquents sont :

  • –annotate : permet d’enregistrer plus d’éléments dans le tag, comme un message, une date de création…
  • –list : permet de lister les tags du dépot
  • –delete nom-du-tag : permet de supprimer un tag

Gérer les branches (git branch)

Avec Git, on crée une branche à chaque nouveau développement du projet : ajout de fonctionnalité, correction de bug… Les branches sont un moyen efficace de permettre à plusieurs versions d’un projet de cohabiter et d’évoluer séparément. Les branches de correctif ou de fonctionnalité peuvent ensuite être réintroduites dans les branches communes à l’aide d’une fusion ou d’un rebase.

Une branche est toujours créée à partir d’un commit précis d’une autre branche. La nouvelle branche et celle d’origine partageront donc ce commit qui sera leur ancêtre commun. C’est à partir de ce commit que les branches divergent. Pour créer une branche, il faut utiliser la syntaxe : git branch nom-de-la-branche.

Les argument les plus fréquents sont :

  • –list : affiche les branches locales, la branche courante est suffixée d’un astérix
  • –all : affiche les branches du dépôt
  • –delete nom-de-la-branche : supprime la branche
  • –contains commit : liste les branches contenant le commit spécifié

Fusionner 2 branches (git merge)

La fusion permet d’intégrer les modifications d’une branche dans une autre. Cela permet d’intégrer régulièrement le travail d’un.e développeur.se à la branche commune de développement. Pour cela, il faut se placer dans la branche de réception, puis exécuter la commande git merge nom-de-la-branche-a-intégrer. La commande va créer un nouveau commit qui contient les modifications de la branche à intégrer. La fusion peut entrainer des conflits (voir paragraphe suivant…)

Les arguments les plus fréquents sont :

  • –no-ff : force la commande à commiter les résultats du merge même dans le cas d’une avance rapide.
  • -m « message » : permet de personnaliser le message du commit pour garder un historique lisible. Utiliser –no-ff pour être sûr q’un commit soit effectué.

Résoudre les conflits

Un conflit survient lorsque Git trouve des modifications différentes aux mêmes endroits du fichier entre les deux branches. Il faut donc l’aider à savoir quel code placer dans la version finale.

La commande git merge place des séparateurs <<< , >>> et ||| dans les fichiers concernés. Le code entre les séparateurs << et ||| montre le code de la branche courante. Celui entre les séparateurs ||| et >> montre la version contenue sur la branche à fusionner.

Il convient donc d’éditer les fichiers concernés (visibles avec git status), pour supprimer les séparateurs et ne garder que le code désiré au final. Il est courant de faire un mélange des 2 versions pour avoir la version finale.

Il faut ensuite ajouter le fichier à l’index (git add) et le commiter (git commit).

Rebaser (git rebase)

Se placer dans la branche de réception, puis saisir la commande git rebase nom-de-branche-a-intégrer.

L’argument le plus fréquent est –onto commit, qui permet de définir le commit qui servira de référence à l’intégration des comits..

Se placer sur une branche (git checkout)

Utiliser la commande git checkout nom-de-la-branche. L’agument -b permet de créer (et de se placer sur) la branche de destination à partir de la branche courante. commit chemin-du-fichier permet de restaurer le fichier tel qu’il était dans le commit.

Se placer sur une version (git reset)

Permet de supprimer les modifications du répertoire de travail ou de faire remonter un commit en faisant remonter la référence de la branche.

A la différence de git checkout, en fonction de ses arguments, git reset va mettre à jour l’index du dépôt et le répertoire de travail. Lors de l’utilisation de git reset à partir d’une tête de branche, cette branche pointera vers le commit visé. Il faut être à l’aise avec git reset pour l’utiliser, car cette commande peut être destructrice et entraîner des pertes de code. Pour faire pointer le HEAD et l’index sur un commit, il faut utiliser la commande : git reset commit.

Ses argument fréquents sont :

  • –soft : met à jour uniquement le HEAD
  • –hard : met à jour le HEAD, l’index et également le répertoire de travail. Est souvent utilisé avec HEAD comme commit dans le but de supprimer les modifications du répertoire de travail.

Cloner un dépôt (git clone)

Permet à un.e développeur.se d’intègrer un projet dont le dépôt existe déjà. La commande est : git clone lien-vers-le-dépôt. On peut utiliser l’argument –bare qui permet de spécifier que le nouveau dépôt est uniquement un dépôt distant qui ne nécessite pas de répertoire de travail. –recursive permet d’initialiser les dépôts intégrés (submodules) du dépôt.

Envoyer des commits (git push)

La commande est : git push nom-du-remote nom-de-la-branche.

L’argument –set-upstream permet d’envoyer les nouvelles références avec les commits (utilisé pour l’envoi d’une nouvelle branche). –all permet d’envoyer les commits de toutes les branches.

Mettre le dépôt à jour (git pull)

Avant de créer une branche pour un nouveau déploiement ou au moment de se mettre à jour (revue de code ou déploiement). Utiliser la commande git pull. Les nouveaux commits seront intégrés à la branche actuelle. L’argument –all récupère tous les commits des branches distantes suivies.

Supprimer un commit (git revert)

La commande est git revert commit. Cette commande crée le commit inverse du commit à supprimer, dans inverser les modifications. Ne pas oublier de purger le commit.

Copier coller un commit (git cherry-pick)

Pour intégrer une partie des commits d’une branche dans une autre. Se positionner sur la branche de réception, puis utiliser la commande git cherry-pick commit. Le commit sera alors appliqué dans la branche courante.

Mettre de coté des modifications (git stash)

Si l’on doit changer de branche mais que le développement n’est pas terminé sur la branche courante, il est parfois préférable de mettre de coté les modifications plutôt que de commiter.

La commande git stash permet de mettre de coté des modifications pour les rappliquer par la suite. Cette commande possède des sous commandes (save, apply…) pour effectuer différentes actions. La commande générique est : git stash save nom-du-stash. Il est possible d’y intégrer des fichiers non suivis avec l’argument –include -untracked.

Les arguments fréquents sont :

  • git stash list : liste les stash enregistrés
  • git stash apply nom-du-stash : réaplique un stash sauvegardé (en le conservant)
  • git pop nom-du-stash : réplique le stash et le supprime automatiquement
  • git stash show nom-du-stash : affiche les détails d’un stash
  • git stash branch nom-de-la-branche nom-du-stash : crée une branche à partir du stash
  • git stash drop nom-du-stash : supprime le stash

Le journal des événements

Pour voir l’historique du pointeur HEAD, on peut consulter le journal des références (reflog). On voit alors sur quels commits HEAD à pointé. La commande à utiliser est git reflog. L’argument le plus fréquent est –all, qui permet d’obtenir le reflog de toutes les références et pas uniquement de HEAD.

Votre commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.