1. Use a tracked directory for Git hooks: `git config --local core.hooksPath 'git-hooks'`.
2. Create format.bash and lint.bash.
2.1. Run `black` and `isort` in format.bash.
2.2. Run `flake8`, `mypy`, `black` and `isort` in lint.bash.
2.3. Run lint.bash in the pre-commit hook.
2.4. By default, lint/format only files which are different from origin/master to save time: `git diff --diff-filter=d --name-only -z origin/master "[asterisk].py"`.
3. In CI, run lint.bash with `--all` or some other keyword to verify formatting on every file: `git ls-files -z -- "[asterisk].py"`.
After more than a year with this setup I absolutely adore it.
I've found git hooks to be more trouble than they're worth.
But as long as it's enforced in CI you can leave it up to individual team members how they want to do it.
Of course that doesn't help if you're setting up the formatter for the first time, or want to upgrade to a new version.
Some tools like GitHub's diff do try to deemphasize whitespace but it's pretty limited.