Chapitre 9 sur 13

Git pathspec : Restreindre une commande à certains éléments

Laisser un commentaire

De nombreuses commandes Git acceptent des paramètres indiquant des fichiers ou répertoires sur lesquels agir. C’est notamment le cas de add, log, diff, checkout, rm pour ne citer que les plus courantes.

Le paramètre que ces commandes acceptent se nomme pathspec. Dans son expression la plus simple, il s’agit simplement d’un nom de fichier ou de répertoire. Cependant, comprendre la spécification pathspec permet de faire bien plus : exclure un fichier, ne sélectionner que les fichiers possédants une extension donnée etc.

Le séparateur de paramètres

La première chose à connaître est le séparateur des paramètres : --. Vous avez peut-être déjà rencontré ce double-tirets à maintes reprises sans vraiment en comprendre l’utilité. Ce “paramètre”, qui est inclus dans de très nombreuses commandes Unix, signifie que tout ce qui est passé après lui n’est pas une option. Ainsi, il permet de lever l’ambiguïté qu’il pourrait exister dans certains cas.

# Création avec touch d'un fichier nommé "--param"
touch --param
touch: illegal option -- -

# Deuxième tentative avec le "--"
touch -- --param

Fichiers ou répertoires

Il s’agit de l’usage le plus courant. On passe à Git les fichiers et/ou répertoires que l’on souhaite voir utilisés par la commande.

git add . # ajoute tout le répertoire courant
git add css/ # ajoute le répertoire des styles
git add README.md # ajoute juste le fichier readme

Bien entendu, nous pouvons passer plusieurs pathspec à la commande.

# ajoute les répertoires js/ et tests/
git add js/ tests/

Expressions régulières

La pathspec supporte quelques éléments de la syntaxe REGEX. Vous connaissez certainement le glob pattern, lequel indique que l’on souhaite appliquer la commande à tous les fichiers. Ce dernier est le plus connu de la spécification pathspec. Il existe bien entendu des paramètres permettant d’être plus précis, cela offre un gain de productivité non négligeable.

De manière plus précise, le glob pattern inclus tous les caractères ainsi que les sous-répertoires. Ainsi, *.txt sélectionnera tous les fichiers ayant l’extension “txt” dans le répertoire courant et ses sous-répertoires. Nous l’avons expliqué dans commandes indispensables, il est important de placer les wildcar entre guillemets afin de s’assurer qu’il n’est pas interprété par le shell avant d’être transmis à Git.

En plus du glob, vous pouvez utiliser les instructions REGEX ? et [].

git ls-files '*.html' # liste tous les fichiers html (répertoire courant et sous-répertoires)
git ls-files '*.jpe?g' # liste toutes les images jpeg (extension jpg ou jpeg)
git ls-files '*.[tj]s' # liste tous les fichiers .js ou .ts

Bien entendu, les crochets peuvent également recevoir les classes de caractères : :alpha:, :alnum:, :space:, :digit: etc. Voud pouvez vous référer à mon article sur les expressions régulières pour plus d’informations sur les classes de caractère.

Les flags pathspec

La spécification pathspec accepte des drapeaux (ou signatures magiques) permettant d’en modifier le comportement. Ces flags prennent la forme (:flag) et sont au nombre de six. Voyons chacune d’entre eux dans le détail.

top

Ce flag permet de considérer que la commande est exécutée depuis la racine du projet Git plutôt que depuis le répertoire courant (s’il s’agit d”un répertoire différent de la racine).

git ls-files ':(top)*.css`
git ls-files '/*.css' # commande raccourcie

Vous obtiendrez la liste de tous les fichiers CSS du projet, même si la commande est exécutée depuis un répertoire ne contenant que des fichiers JavaScript.

icase

Assez facile à comprendre, le flag icase permet d’ignorer la case. Par exemple, les fichiers images jpeg et png ont parfois leurs extensions en majuscules. On pourra donc facilement s’abstraire de cette contrainte avec icase.

git ls-files ':(icase)*.jpe?g' ':(icase)*.png'

literal

Le drapeau literal permet de considérer tous les caractères comme litéraux, sans leur prêter aucune signification particulière. Il n’est ainsi pas besoin d’échapper les wildcards * et ?.

git add ':(literal)*.html' # ajoute le fichier nommé *.html

C’est un cas assez peut courant, mais il est toujours bon de savoir qu’il existe.

glob

Git traite le glob pattern de manière un peu différente de ce à quoi nous sommes habitués avec sous Linux et Unix. En effet, * inclut les sous répertoires. Dans Bash par exemple, ls *.js ne s’applique qu’aux fichiers “.js” du répertoire courant. Il faut utiliser le double astérisque pour considérer les sous-répertoires. Le flag glob permet de restaurer ce comportement.

git ls-files ':(glob)*.json' # ne liste que les json du dossier courant
git ls-files ':(glob)vendors/**/*.js' # liste les fichiers json dans vendors et ses sous-dossiers

attr

Git permet de définir des attributs spécifique pour certains types de fichiers. Le flag attr permet de cibler les fichiers selon ces attributs. La syntaxe permet plusieurs choses :

git ls-files ':(attr:eol)' # fichiers dont l'attribut eol est renseigné
git ls-files ':(attr:!eol)' # fichiers dont l'attribur eol n'est pas renseigné
git ls-files ':(attr:-eol)' # fichiers dont l'attribut eol est désactivé
git ls-files ':(attr:eol=lf)' # fichiers dont l'attribut eol est égal à lf

exclude

Le drapeau exclude fonctionne différemment des autres. Il permet d’exclure des éléments de la sélection. Lorsque les autres pathspecs ont été inerprétés, celui-ci permet de filtrer leur sélection.

git add '*.js' ':(exclude)*.min.*js # les fichiers js minifiés seront exclus de la sélection
git add '*.js' ':!*.min.*js # syntaxe raccourcie
git add '*.js' ':^*.min.*js # syntaxe raccourcie alternative

Il est bien entendu possible de combiner ces drapeaux afin d’affiner encore la sélection. La seule limite à connaître est qu’il n’est pas possible, en toute logique, de combiner glob et literal car ce dernier neutralise la sémantique des wildcards.

Pour combiner plusieurs drapeaux, il suffit de les séparer par des virgules.

git ls-files -- ':(top,icase)*.jpe?g'

C’est grâce à la maîtrise de ces aspects de Git que la ligne de commande prend vraiement tout son sens par rapport aux interfaces graphiques. Le pathspec n’est pas si complexe à appréhender si on prend un mininum le temps de le comprendre. Pourtant, il offre une grande finesse dans la sélection de nombreuses commandes d’usage quotidien.

Commentaires

Rejoignez la discussion !

Vous pouvez utiliser Markdown pour les liens [ancre de lien](url), la mise en *italique* et en **gras**. Enfin pour le code, vous pouvez utiliser la syntaxe `inline` et la syntaxe bloc

```
ceci est un bloc
de code
```