diff --git a/docs/pre-commit.md b/docs/pre-commit.md new file mode 100644 index 0000000..1a05edb --- /dev/null +++ b/docs/pre-commit.md @@ -0,0 +1,181 @@ +# Base files and pre-commit hooks + +## Git dotfiles + +This repository contains baseline `.gitignore` and `.gitattributes` files with +configurations applicable to most project. Extend and modify them to support +tools and languages specific to your project. + +### The `.gitignore` file + +The `.gitignore` file has been generated on [Toptal's .gitignore +generator][gitignore.io], and ignores common files generated by: + +- Windows +- Linux +- Visual Studio Code + +To update the `.gitignore` file to exclude generated tools for the tools and +languages specific to your application, navigate to + +and use the generator to create a new `.gitignore` file. + +### The `.gitattributes` file + +The `.gitattributes` file was introduced to manage file endings (`CRLF`/`LF`) on +files pushed to the repository. Specifically, the +[`Common.gitattributes`][gitattributes-source] file from the +[alexkaratarakis/gitattributes][gitattributes-repo] repository is used as a +baseline, which sets many other attributes, including appropriate line endings +for common file types. + +Specifically, the provided `.gitattributes` file: + +- auto detects text files and performs LF normalization +- explicitly declares common files as either text and binary +- explicitly declares known OS-specific files as ending with CRLF or LF +- converts complex file types to text (doc, pdf, etc) before a diff +- ignore the .gitignore and .gitattribute files when exporting the repo + +## pre-commit hooks + +This repository uses [pre-commit][pre-commit] as a Git hook management tool. + +These hooks are general enough to be used in all projects. Depending on your +project's requirements, you will want to modify these hook configurations or add +your own. + +The hooks provided as part of this repository are: + +- [Check Yaml][hook-yaml] +- [Fix End of Files][hook-eof] +- [Trim Trailing Spaces][hook-spaces] +- [Check for case conflicts][hook-case] +- [Detect Private Key][hook-private] +- [Mixed line ending][hook-ending] +- [Prettier][hook-prettier] +- [commitlint][hook-commitlint], enforcing the [conventional + commit][conventional-keywords] specification + +The sections below show how the pre-commit hooks can help implement best +practices and avoid errors before your code is pushed to the repository. + +### Check Yaml + +This hook checks `.yaml` files for valid syntax, using the [ruamel.yaml][ruamel] +YAML loader/dumper for Python. + +[![asciicast][asciinema-yaml-svg]][asciinema-yaml-link] + +### Fix End of Files + +UNIX applications typically expect a new line at the end of every file (some +examples are the GNU diff and sort tools—[see this StackExchange question for a +detailed explanation][stackexchange-blank-lines]). This hook ensures that all +files pushed to the repository end with a new line. + +[![asciicast][asciinema-eof-svg]][asciinema-eof-link] + +### Trim Trailing Spaces + +This hook removes invisible blank characters at the end of a line. + +[![asciicast][asciinema-spaces-svg]][asciinema-spaces-link] + +### Check for case conflicts + +File names in Linux operating systems are case-sensitive—the files `FILE.txt` +and `file.txt` are considered as two distinct files. Windows files, however, are +case-insensitive. + +To prevent conflicts between the two operating systems, this hook ensures that +no two files have the same name, regardless of the case used. + +[![asciicast][asciinema-case-svg]][asciinema-case-link] + +### Detect Private Key + +This hook detects private keys and other secrets that might have been +inadvertently staged, and blocks the commit. + +> **Note:** This hook only checks files for [certain +> keywords][private-key-words]—if a private key is exported as binary (by +> omitting the `--armor` flag when exporting PGP keys, for example), this hook +> won't flag the file and allow potentially sensitive data to be committed. + +[![asciicast][asciinema-key-svg]][asciinema-key-link] + +### Mixed line endings + +This hook flags files that contain both Windows (CRLF) and Linux (LF) file +endings. + +[![asciicast][asciinema-ending-svg]][asciinema-ending-link] + +### Prettier + +This hook runs the [Prettier][prettier] code formatter on all files before +committing. + +[![asciicast][asciinema-prettier-svg]][asciinema-prettier-link] + +### commitlint + +This commit-msg hook verifies that commit messages follow the [Conventional +Commits][conventional-standard] specification. A full list of checks can be +found [here][conventional-keywords]. + +> **Note:** This commit hook needs to be installed separately, using +> `pre-commit install --hook-type commit-msg` + +[![asciicast][asciinema-commitlint-svg]][asciinema-commitlint-link] + +[gitignore.io]: https://gitignore.io +[gitattributes-source]: + https://github.com/alexkaratarakis/gitattributes/blob/809623f5456638a8351291906aad39432c8366f1/Common.gitattributes +[gitattributes-repo]: https://github.com/alexkaratarakis/gitattributes +[pre-commit]: https://pre-commit.com +[stackexchange-blank-lines]: + https://unix.stackexchange.com/questions/18743/whats-the-point-in-adding-a-new-line-to-the-end-of-a-file + + + +[asciinema-yaml-svg]: https://asciinema.org/a/304129.svg +[asciinema-yaml-link]: https://asciinema.org/a/304129 +[asciinema-eof-svg]: https://asciinema.org/a/304097.svg +[asciinema-eof-link]: https://asciinema.org/a/304097 +[asciinema-spaces-svg]: https://asciinema.org/a/304086.svg +[asciinema-spaces-link]: https://asciinema.org/a/304086 +[asciinema-case-svg]: https://asciinema.org/a/304090.svg +[asciinema-case-link]: https://asciinema.org/a/304090 +[asciinema-key-svg]: https://asciinema.org/a/304082.svg +[asciinema-key-link]: https://asciinema.org/a/304082 +[asciinema-ending-svg]: https://asciinema.org/a/304109.svg +[asciinema-ending-link]: https://asciinema.org/a/304109 +[asciinema-prettier-svg]: https://asciinema.org/a/304492.svg +[asciinema-prettier-link]: https://asciinema.org/a/304492 +[asciinema-commitlint-svg]: https://asciinema.org/a/304493.svg +[asciinema-commitlint-link]: https://asciinema.org/a/304493 +[prettier]: https://prettier.io +[private-key-words]: + https://github.com/pre-commit/pre-commit-hooks/blob/d9ccd95055e5e3e6057b41b124857c93280b6bdd/pre_commit_hooks/detect_private_key.py#L5-L14 +[conventional-standard]: https://www.conventionalcommits.org/en/v1.0.0/ +[conventional-keywords]: + https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional +[hook-yaml]: + https://github.com/pre-commit/pre-commit-hooks/blob/d9ccd95055e5e3e6057b41b124857c93280b6bdd/pre_commit_hooks/check_yaml.py +[ruamel]: https://pypi.org/project/ruamel.yaml/ +[hook-eof]: + https://github.com/pre-commit/pre-commit-hooks/blob/d9ccd95055e5e3e6057b41b124857c93280b6bdd/pre_commit_hooks/end_of_file_fixer.py +[hook-spaces]: + https://github.com/pre-commit/pre-commit-hooks/blob/d9ccd95055e5e3e6057b41b124857c93280b6bdd/pre_commit_hooks/trailing_whitespace_fixer.py +[hook-case]: + https://github.com/pre-commit/pre-commit-hooks/blob/main/pre_commit_hooks/check_case_conflict.py +[hook-private]: + https://github.com/pre-commit/pre-commit-hooks/blob/main/pre_commit_hooks/detect_private_key.py +[hook-ending]: + https://github.com/pre-commit/pre-commit-hooks/blob/d9ccd95055e5e3e6057b41b124857c93280b6bdd/pre_commit_hooks/mixed_line_ending.py +[hook-prettier]: + https://github.com/prettier/prettier/tree/d746cd73becfa91185f42a7cefb4ebe79145d771 +[hook-commitlint]: + https://github.com/alessandrojcm/commitlint-pre-commit-hook/tree/6bc8fdadc259830d59d9904dc22b7fe0d3ffb49a