Le blog tech de Nicolas Steinmetz (Time Series, IoT, Web, Ops, Data)
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.