Switching between a corporate repo (Macquarie SSO) and personal repos, the thing you dread most is pushing with the wrong identity, or having your AWS profile silently mismatch. This post walks through a real debugging session: starting from one diagnostic command and ending with a clear mental model of includeif vs direnv — two mechanisms that get mixed up constantly.
The starting point was this command (explained only, not executed):
echo "--- local ---"; git -C ~/ws/qa/edr-nonstandard-etl config --local --get-regexp 'ssh|url|core\.' 2>/dev/null
echo "--- global ---"; git config --global --get-regexp 'ssh|url|includeif|core\.ssh' 2>/dev/null
echo "--- direnv allow list ---"; ls ~/.local/share/direnv/allow 2>/dev/null | head; direnv status 2>&1 | head -8
git -C ~/ws/qa/edr-nonstandard-etl config --local --get-regexp 'ssh|url|core\.'
-C <path>: run a git command against a specific repo without cd-ing thereconfig --local: reads only that repo’s own .git/config, ignoring global settings--get-regexp 'ssh|url|core\.': regex-matches key names to surface anything related to ssh, url, or core. (e.g. core.sshCommand, url."xxx".insteadOf rewrite/proxy rules)git config --global --get-regexp 'ssh|url|includeif|core\.ssh'
Same idea, but against ~/.gitconfig, with includeif added — the mechanism for conditionally pulling in a different config file, commonly used for “this SSH key for work directories, that one for personal.”
ls ~/.local/share/direnv/allow 2>/dev/null | head
direnv status 2>&1 | head -8
Taken together, this command answers one question: “which SSH identity / URL rewrite rules does this repo actually use, and has direnv been allowed to run here?” — a classic checklist for multi-identity dev environments.
includeifdecides who you are (git identity).direnvdecides what environment you’re in (env vars / PATH / secrets). One swaps your ID card, the other swaps your wallet.
Defined in ~/.gitconfig:
[includeif "gitdir:~/ws/mq/"]
path = ~/.gitconfig-macquarie
[includeif "gitdir:~/ws/personal/"]
path = ~/.gitconfig-personal
gitdir:), or by branch name (onbranch:, git 2.36+)[user] name/email, [core] sshCommand, etc. from the target filegit config --get shows the merged result directly🩸 Hard-earned lesson: gitdir: matches the repo directory itself (where .git lives). If you got there via a symlink or a git worktree, the path match can silently fail — use gitdir/i: (case-insensitive) or debug with the absolute path.
.envrc file + direnv allow:
# ~/ws/mq/edr-nonstandard-etl/.envrc
export AWS_PROFILE=mqu-dev
export GIT_SSH_COMMAND="ssh -i ~/.ssh/mq_id_ed25519"
cds into the directory; the direnv hook auto-sources the filedirenv allow once (this is exactly what the original command’s allow-list check was verifying) — and editing .envrc invalidates that trust, requiring re-allow, to stop a malicious repo from silently running code🩸 Hard-earned lesson: code inside .envrc is a real, executable shell script, not declarative config. If you git pull an unfamiliar repo that ships its own .envrc, don’t blindly direnv allow it — that’s equivalent to letting someone else’s script run arbitrary commands on your machine.
includeif only changes your git-level identity — it does not automatically load the matching SSH key into your agent, nor switch your AWS profile. So the full chain looks like:
cd into ~/ws/mq/edr-nonstandard-etl/
↓ direnv auto-loads
GIT_SSH_COMMAND points to the mq key + AWS_PROFILE=mqu-dev
↓ includeif matches gitdir
git identity switches to the macquarie email
Each system owns one link in the chain — if either link is misconfigured, you get “pushed with the wrong identity” or “AWS permissions don’t match” bugs, and debugging only one side will miss the other.
includeif = static, git-internal, owns identitydirenv = dynamic, shell-level, owns environment variables, and requires explicit trust