Git: hook commit-msg pour adopter les conventional commits


22/09/2020 git commit conventional commit

Les “conventional commits” apportent une formalisation des messages de commit git. Ils sont de la forme :

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Pour reprendre quelques exemples :

# Commit message with no body
feat: allow provided config object to extend other configs

# Commit message with scope
feat(lang): add polish language

# Commit message with ! to draw attention to breaking change
refactor!: drop support for Node 6

# Commit message with both ! and BREAKING CHANGE footer
refactor!: drop support for Node 6

BREAKING CHANGE: refactor to use JavaScript features not available in Node 6.

En forçant ce formalisme, le développeur est un peu moins tenté d’avoir un historique de commit du style :

fix  button
typo
add some tests
add some tests
...

Au lieu de faire un commit à chaque sauvegarde du fichier ou presque, il va commencer à “raconter une histoire” :

fix: button on home page does not work on IE6
docs: typo in the README file
feat: add some tests for module XXX

Cela a le mérite aussi de générer un changelog plus agréable à lire. Si en plus, on rajoute par ex un identifiant de ticket, on peut alors facilement retracer l’historique d’un changement et sa raison d’être :

fix(123): button on home page does not work on IE6
docs(211): typo in the README file
feat(175): add some tests for module XXX

Un peu à la manière de “Properly managing your .gitignore file”, on peut vouloir que le hook git s’applique à tous nos dépôts présents et à venir et ne pas avoir à contribuer le hook à chaque dépôt git.

# Create ~/.git-templates/hooks
mkdir -p ~/.git-templates/hooks
# Create commit-msg file and make it executable
touch ~/.git-templates/hooks/commit-msg
chmod +x ~/.git-templates/hooks/commit-msg

Ajoutons ensuite notre hooks dans ~/.git-templates/hooks/commit-msg :

#!/usr/bin/env python3
# Original source: https://github.com/prahladyeri/enforce-git-message/
# Extended with BREAKING CHANGE, exclamation mark support (!) and space before " : " for French people

import re, sys, os

examples = """+ 61c8ca9 fix: navbar not responsive on mobile
+ 479c48b test: prepared test cases for user authentication
+ a992020 chore: moved to semantic versioning
+ b818120 fix: button click even handler firing twice
+ c6e9a97 fix: login page css
+ dfdc715 feat(auth): added social login using twitter
+ b235677 BREAKING CHANGE: remove support for XXX
+ a234556 revert!: back to version X.Y.Z for component ZZZ
+ b123456 feat : we support space before : for French people :-)
"""

def main():
    pattern = r'(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test|BREAKING CHANGE)(\([\w\-\s]+\))?!?\s?:\s.*'
    filename = sys.argv[1]
    ss = open(filename, 'r').read()
    m = re.match(pattern, ss)
    if m == None:
        print("\nCOMMIT FAILED!")
        print("\nPlease enter commit message in the conventional format and try to commit again. Examples:")
        print("\n" + examples)
        sys.exit(1)

if __name__ == "__main__":
    main()

Il faut ensuite indiquer à git que vos templates sont dans ce dossier :

git config --global init.templatedir '~/.git-templates'

Pour les dépots git existants, il faut réinitialiser votre dépôt git :

cd /path/to/git/repo
git init
Dépôt Git existant réinitialisé dans /path/to/git/repo/.git/

Vous pouvez alors commencer à travailler dans votre repo et valider le bon fonctionnement du hook.

Le Blog

Nous partageons ici notre veille et nos réflexions

Article(s) lié(s)

Nuage de tags

kubernetes docker influxdb traefik timeseries grafana kafka ansible elasticsearch postgres python warp10 aws sécurité mysql redis terraform tick cassandra cloud helm ovh git telegraf rancher swarm test timescaledb chronograf docker-compose flux résilience architecture arm confluent devops gitlab ksql log machine-learning microservice monitoring prometheus ptsm s3 serverless spark angularjs api cert-manager cncf container dashboard dns gcp graphql hashicorp iac ingress java javascript opensource operator optimisation raspberrypi service-mesh sql stream vscode warpscript windows bilan csp cérénit documentation elastic flows gke hpkp jenkins kafka-streams kapacitor kibana kubedb lambda lean licence maesh maintenance mariadb microsoft mobile nginx npm orientdb perspective pipeline redhat rest rethinkdb reverse-proxy rook sauvegarde scaleway ssh agile apm automatisation azure bash big-data ceph certificat ci/cd cli cluster containerd continous-delivery continous-integration cookie deployment diff fluxlang forecast framework gdpr grav hsts http/3 https hypriot hébergement influxace influxdata influxdays istio jq json k3s lets-encrypt linux load-balancer longhorn meetup molecule mongodb nosql nvidia openebs percona performance php pip postgresql reaper registry replication rpi rsyslog scale secrets société solr sre systemd timezone tls vault virtualenv vitess vue.js wagtail warpfleet yarn accessibilité acme akka alerte alibaba amazon-emr amqp anonymisation anthos apache-pulsar ara arima arrow audit bastion beam beat bigdatahebdo bounded-context branche brigade browser buildkit cahier-des-charges calico cassandra-reaper cd cdc cdk centralisation-de-logs certificats chart checklist chrome ci cilium cloud-init cloud-native cloud-storage clusterip cnab cni cockroachdb code codeurs-en-seine commit confluence conftest consul continous-deployment conventional-commit coreos cors covid19 cqrs crash cron crontab csi csrf css curl d3.js daemonset data data-engineer data-pipelining data.gouv.fr datacenter dataviz date date-scientist ddd debezium debian delta deprek8 desktop devoxx dig distributed-systems dive docker-app docker-hub docker-registry docker-swarm documentdb dog dokcer données-personnelles draft drop-in duration déploiement développement-du-site e-commerce ebs ec2 edge elassandra electron elk engineering entreprise ergonomie etcd event-sourcing faas facebook faisabilité falcor feature-policy fedora feed filebeat firebase firefox fish flash flask fleet flink fluentd formation foundation frontend fsync fullstack github gitignore gitlab-ci glacier glowroot google google-cloud-next gpu grid géospatial hacker hadoop haproxy harbor hdfs header html html5 http hue ia iaac ibm immutable incident index influxcloud infrastructure-as-code ingénierie inspec jquery jwt k3d k8s k9s kotlin kubeadm kubecon kubectl laravel letsencrypt linky liste-de-diffusion loadbalancer logstash logstatsh loi mailing-list management maturité mesh mesos message metallb micro-service mot-de-passe mqtt multi-cloud médecine métrique network newsletter nodeport nomad null object-storage observability observabilité opa opendata openmetrics openshit openssh openstack openweb over-engineering ovhcloud packaging pandas parquet partiql password persistent-volume-claim pipenv pod podman portainer portworx prediction prescience ptyhon publicité pubsub pulsar push pyenv quasardb quay questdb queue quic ram rambleed raml react recaptcha recherche redistimeseries reindex reinvent reliability responsive revocation revue-de-code rgpd rkt rolespec root rootless rpo rto runc rust rwd safe-harbor scalabilité scanner schema scp sdk search select serverless-architecture service-account service-worker setuptools sftp sha1 sharding shell shipyard sidecar souveraineté-numérique spinnaker spécifications sri ssh-agent ssl stash statistique storage superset suse sympa syslog-ng terracost terrascan test-unitaire tidb tiers timer training travail tsl ubuntu unikernel unit ux vendredi victoria-metrics vie-privée virtualbox virtualisation vm vnc volume voxxeddays vpc warpstudio web yaml yq yubikey

Syndication

Restez informé(s) de notre actualité en vous abonnant au flux du blog (Atom)