I organize my home folder something like this:
/home/varl ├── dev │ ├── work │ └── personal └── .gitconfig
In the main Git configuration file ~/.gitconfig I set my defaults:
# ~/.gitconfig
[pull]
rebase = true
[branch]
autosetuprebase = always
[commit]
gpgSign = true
[core]
editor = vim
[user]
name = Viktor Varland
email = varl@personal.com
signingkey = PERSONAL_KEY_TO_SIGN_WITH
These settings are used everywhere, which is the normal way to do
things. However I would like to change user.email and
user.signingkey when I am working on different projects (e.g. work
account and key for work, and personal account and key for, well,
personal projects).
For each context under ~/dev I add another .gitconfig file:
/home/varl ├── dev │ ├── work │ │ └── .gitconfig │ └── personal │ └── .gitconfig └── .gitconfig
Back in the main ~/.gitconfig, add the includeIF directive to
conditionally include[1] configuration for different contexts:
# ~/.gitconfig
# ... trunc ...
[includeIF "gitdir:~/dev/work/"]
path = ~/dev/work/.gitconfig
[includeIF "gitdir:~/dev/personal/"]
path = ~/dev/personal/.gitconfig
This makes Git load additional configuration if I am using Git within
e.g. ~/dev/work.
In ~/dev/work/.gitconfig I can override or set new options valid for the
repos within ~/dev/work:
# ~/dev/work/.gitconfig
[user]
name = Viktor Varland
email = viktor.varland@work.com
signingKey = WORK_KEY_TO_SIGN_WITH
Note that I can use a different git user when working in repos below ~/dev/work than I use for my personal stuff.
Now, create the folder ~/dev/work/.hooks. We are going to use this to
define hooks that apply for all the projects under ~/dev/work.
/home/varl ├── dev │ ├── work │ │ ├── .hooks │ │ └── .gitconfig │ └── personal │ └── .gitconfig └── .gitconfig
# ~/dev/work/.gitconfig
[core]
hooksPath = ~/dev/work/.hooks
# ... trunc ...
This makes it so that we can use global git hooks for all repos that belong to the same context, in this example, work.
For example, the ~/dev/work/.hooks/pre-commit hook looks like this:
#!/bin/bash if [[ -f "$PWD/package.json" ]]; then npm run --if-present lint fi
So each time we try to commit in a repo that has a main package.json file, it
attempts to run the lint script.
We could add similar conditional statements for Rust, Go, Java, as well, and have a hook that does (mostly) the right thing based on the project.
The pre-commit script can be customized to run validation tools per repo, or made general like above.
Hooks can also be skipped anytime with the --no-verify flag[2].
On pre-push we can do something similar, but for tests.
[1] https://git-scm.com/docs/git-config#_includes [2] https://git-scm.com/book/fa/v2/Customizing-Git-Git-Hooks