Chapitre 13 sur 13
Aller plus loin : notions utiles
Ce chapitre regroupe différentes notions et fonctions de Git qui n’ont pas su trouver leur place dans les chapitres précédents. Elle n’en sont pas moins dénué d’intérêt !
Effacer les fichiers non suivis
git clean
permet de nettoyer le projet Git de tout fichier non suivi qui n’est pas référencé dans .gitignore
.
Application partielle
Qu’il s’agisse d’enregistrer des modifications ou de restaurer certains fichiers, il arrive que nous ne souhaitions restaurer que certaines parties de nos modifications au sein d’un fichier. C’est tout à fait possible avec l’option -p
. Cette option, --patch
dans sa version longue, existe dans de nombreuses commandes :
git add
,git stash
,git restore
,git checkout
,git reset
.
Dans le cas de stash, elle passe en revue les modifications et vous demande pour chaque bloc de modification si vous souhaitez ou non le restaurer.
On vous présente alors un à un des blocs de modifications avec, pour chacun, une liste d’options. Vous pouvez entrer “?” pour obtenir des informations plus détaillées. Les options sont les suivantes.
y
: ajouter ce bloc à l’indexn
: sauter ce blocq
: quitter ce mode interactif et n’ajouter aucun des blocs suivants à l’indexa
: ajouter ce blocs et les suivants à l’indexd
: n’ajouter aucun des blocs suivants à l’indexg
: aller directement à un bloc/
: recherche un bloc via une regexj
: ne rien décider et passer au bloc non décidé suivantJ
: ne rien décider et passer au bloc suivante
: éditeur ce bloc?
: afficher l’aide
Dans le cas du git add
, on peut avantageusement utiliser l’option -i
ou --interactive
afin d’avoir à la fois le patch mais aussi la possibilité de sélectionner de manière interactive quels sont les fichiers à ajouter à l’index.
Rebase avancé
Nous avons déjà vu l’usage du rebase à plusieurs reprises. Il existe cependant un type de rebase avancé que nous n’avons pas abordé, il s’agit du rebase --onto
. Ce dernier permet, tout comme le rebase interactif, de supprimer des commits. Rien qui ne soit pas déjà faisable avec l’option -i
de rebase, mais le fait de ne pas passer par le mode interactif offre un gain de temps pour de petits changements.
# Pour supprimer des commits d'une branche, il suffit de préciser un intervalle à effacer
# Admettons que l'on veuille supprimer le commit b946f12 dans Jamments
git rebase --onto 01377ca b946f12
On définit le commit 01377ca
comme étant la nouvelle base du commit b946f12
, ce dernier disparaît donc. Il est également possible de spécifier un intervalle.
# Faire disparaitre les trois commits entre 1457146 et 0cb3df9
git rebase --onto 1457146 0cb3df9
Les exemples précédents supposent que nous sommes sur la master. Il est toutefois possible de passer en dernier argument la branche sur laquelle opérer.
Le rebase à trois arguments
Rebase peut également prendre trois arguments. Cela permet de placer une branche créée à partir d’une branche A, sur une branche B. Voyons un exemple.
# État de départ
*---*---*---*---* master
\
*---*---*---*---* featureA
\
*---*---* featureB
# État souhaité
*---*---* featureB
/
*---*---*---*---* master
\
*---*---*---*---* featureA
Afin d’obtenir ce résultat, nous allons en quelque sorte dire à rebase : “Prend la branche featureB, vois ce qu’elle contient que n’a pas featureA et rejoue l’ensemble comme si featureB avait été créée depuis la master”. La commande Git qui veut dire cela est la suivante.
# On peut aussi le lire comme : inverse master et featureA concernant la base de featureB
git rebase master featureA featureB
Les Git submodules
Pour comprendre de quoi il s’agit, commençons par expliquer le use case. Vous développez un module réutilisable que vous voulez intégrer dans divers projets. Par exemple un petit système de notification.
Soit vous copiez le code dans chaque projet et vous le commitez, mais vous dupliquez le code partout, vous avez des versions différentes etc. Pas pratique. Soit vous ajoutez ce module dans le .gitignore
et vous le clonez dans le projet. À chaque modif, il faudra bien penser à pull, pour récupérer la dernière version, push si vous effectuez des modifs en local etc. Bref, la galère.
De plus, les gens qui cloneront le repo devront télécharger la dépendance manuellement à cause du .gitignore
. C’est pour se soustraire à ces contrainte qu’existent les submodules.
Vous dites à Git de référencer un module depuis un autre repos. Lors d’un clone, le repo tiers sera récupéré avec, si vous effectuez des modifs en local, vous pourrez les pousser depuis le répertoire du submodule et facilement merger depuis la remote.
git submodule add repo-address [path]
Notez que par défaut, le dépôt est cloné dans le répertoire courant. Vous pouvez ainsi spécifier le chemin du sous-module après avoir passé l’adresse du dépôt.
Lorsque vous clonez un repo qui contient des submodules, ces derniers ne sont pas automatiquement importés. Leurs répertoires sont créés mais laissés vides. Deux commandes seront nécessaires pour respectivement initialiser le fichier de config et récupérer lesdits submodules.
git submodule init
git submodule update
# all gooood
Pour creuser ça plus en profondeur, il y a un chapitre dédié dans Git Pro En outre, GitExplorer fournit une doc interactive selon l’action que vous souhaitez effectuer.
Les hooks
Les hooks ne font pas partie du projet Git à proprement parler. Par conséquent, ils ne sont pas clonés avec le projet. Pour les projets collaboratifs, cela ajoute une étape pour tout collaborateur commençant avec le projet. Toutefois, on peut les mettre en place via un processus de build.
Je mets en place les hooks via le npm install
pour les projets JavaScript. Il suffit en effet d’une ligne en sh, compatible avec presque tous les environnements. Ça fonctionne, mais il faut impérativement que la commande de build soit lancée.
# Quelque soit le langage du projet, il suffit d'exécuter cette ligne dans un shell
cd .git/hooks/ && curl -O https://raw.githubusercontent.com/Buzut/git-emojis-hook/master/commit-msg && curl -O https://raw.githubusercontent.com/Buzut/git-emojis-hook/master/prepare-commit-msg && chmod +x * || exit 0
Ce code vient simplement se placer dans .git/hooks/
puis télécharge les deux hooks depuis GitHub et leur donne les droits d’exécution. Simple et efficace.
Depuis la version 2.9 de Git, il est possible de définir un répertoire spécifique pour les hooks. Cela permet donc d’inclure les hooks avec les fichiers du projet, ou même de définir ses propres hooks globaux puisqu’on peut fournir à Git un chemin absolu.
# Définir le répertoire des hooks comme étant .hooks
git config core.hooksPath .hooks
Git ira maintenant chercher les hooks dans .hooks
au lieu de .git/hooks
. Cependant, gardez à l’esprit que la configuration d’un projet n’est pas partagée lors d’un clone. Ainsi, tandis que les hooks placés dans .hooks
sont importés avec le projet, il faudra tout de même que le collaborateur configure core.hooksPath
pour que ces derniers soient actifs.
Committer en tant qu’un autre utilisateur
Certaines commandes qui réécrivent l’historique créé pour vous des commits au nom de quelqu’un d’autre. C’est par exemple le cas de rebase
. Cependant, il arrive que vous commitiez manuellement un bout de code dont vous n’êtes pas l’auteur et que vous souhaitiez donc l’attriber à son auteur réel.
git commit --author="Name <name@email.com>"
Comme nous l’avons mentionné plus haut dans ce chapitre, bien que l’auteur soit la personne renseignée, Git garde tout de même trace du committeur, qio sera vous.
# Si vous souhaitez en avoir le cœur net
git log --format=fuller
Commentaires
Rejoignez la discussion !