How I Handled My Messy Git Config

· 7 minutes read

in my engineering life, i rarely had problems working with multiple git repositories.

things stayed simple until i started working with companies, while still doing freelance work, across multiple machines and multiple git platforms. git became a source of constant friction. not because it was technically complex, but because it was mentally exhausting.

the following setup is my go-to way to remove any mental overhead related to git configuration and identity. (it’s not about knowing Git, it’s about not having to think about it.)

table of contents:


why this setup exists

with multiple accounts and platforms, git becomes unpredictable unless everything is explicit. without proper configuration, you’ll keep running into errors like:

git pull
# git@github.com: Permission denied (publickey).

ssh-add -l
# The agent has no identities.

git push
# remote: Permission denied to personal-username.

or worse: the commit goes through with no error, but your manager notices during code review that all your commits are authored with personal@mail.com instead of your company email. awkward.

the solution is explicit configuration:

  • one key per account (ssh knows which to use)
  • one alias per account (you specify which key)
  • one git identity per folder (automatic, not manual)
  • keychain persistence (keys survive reboot)

this removes the ambiguity.

note: this setup is for local development only. if you SSH into a remote server and run git commands there, this won’t apply — you’d need a separate setup on that machine.


the setup

the following setup is a one-time example configuration for:

  • 1 machine (macOS),
  • 2 github accounts (personal + company),
  • 1 bitbucket (company).

ssh keys (1 key = 1 account)

generate one key per account. no sharing, no reuse.

# generating 3 ssh keys for the 3 accounts
ssh-keygen -t ed25519 -C "personal@email.com" -f ~/.ssh/ssh_github_personal
ssh-keygen -t ed25519 -C "work@companya.com" -f ~/.ssh/ssh_github_company_a
ssh-keygen -t ed25519 -C "work@companyb.com" -f ~/.ssh/ssh_bitbucket_company_b

ssh config (explicit aliases)

this tells ssh which key to use for which platform.

nano ~/.ssh/config

add this:

########################################
# Global (macOS)
########################################
Host *
  AddKeysToAgent yes
  UseKeychain yes          # macOS only — remove this line on Linux
  ServerAliveInterval 60
  ServerAliveCountMax 3

########################################
# GitHub PERSONAL
########################################
Host github.com-personal
  HostName github.com
  User git
  IdentityFile ~/.ssh/ssh_github_personal
  IdentitiesOnly yes

########################################
# GitHub COMPANY A
########################################
Host github.com-company-a
  HostName github.com
  User git
  IdentityFile ~/.ssh/ssh_github_company_a
  IdentitiesOnly yes

########################################
# Bitbucket COMPANY B
########################################
Host bitbucket.org-company-b
  HostName bitbucket.org
  User git
  IdentityFile ~/.ssh/ssh_bitbucket_company_b
  IdentitiesOnly yes

rule: never use github.com or bitbucket.org directly in multi-account setups (the Host). always use aliases.

important: IdentitiesOnly yes forces ssh to use only the specified key. without it, ssh tries all keys until one works (unreliable).

keychain persistence (macOS)

add keys to macOS keychain so they survive reboots.

ssh-add --apple-use-keychain ~/.ssh/ssh_github_personal
ssh-add --apple-use-keychain ~/.ssh/ssh_github_company_a
ssh-add --apple-use-keychain ~/.ssh/ssh_bitbucket_company_b

# verify
ssh-add -l
# all of them should be listed

after this: you never have to run ssh-add again. keys persist across reboots.

git identity per folder (automatic, not manual)

the last piece of the puzzle: making git use the right name/email automatically based on where the repo lives.

without this, you’ll still have to run git config user.email manually in every repo. that’s mental overhead we’re eliminating.

we do that with git’s includeIf directive. it loads different configs based on the folder path.

nano ~/.gitconfig

add this:

[user]
  name = Default Name
  email = default@email.com

[includeIf "gitdir:~/Projects/Personal/"]
  path = ~/.gitconfig-personal

[includeIf "gitdir:~/Projects/Company-A/"]
  path = ~/.gitconfig-company-a

[includeIf "gitdir:~/Projects/Company-B/"]
  path = ~/.gitconfig-company-b

then create the identity files:

~/.gitconfig-personal

[user]
  name = Your Name
  email = personal@email.com

~/.gitconfig-company-a

[user]
  name = Your Name
  email = work@companya.com

~/.gitconfig-company-b

[user]
  name = Your Name
  email = work@companyb.com

rule: organize your repos by specific folders. all personal repos in ~/Projects/Personal/, all company repos in ~/Projects/Company/. git handles the rest.

cloning correctly (this is where most people fail)

here’s the thing: with aliases, you can’t just copy-paste the clone url from github anymore.

github gives you:

git clone git@github.com:username/repo.git

but with our setup, you need to do:

git clone git@github.com-personal:username/repo.git
#                      ^^^^^^^^^ your alias, not github.com

same for company repos:

git clone git@github.com-company-a:company/repo.git

and bitbucket:

git clone git@bitbucket.org-company-b:company/repo.git

quick reference

platformaccountssh aliasclone command
GitHubPersonalgithub.com-personalgit@github.com-personal:user/repo.git
GitHubCompany Agithub.com-company-agit@github.com-company-a:org/repo.git
BitbucketCompany Bbitbucket.org-company-bgit@bitbucket.org-company-b:org/repo.git

migrating existing repos

this is probably the first thing you’ll need to do. if you already have repos cloned with git@github.com:... (without aliases), they’ll break after this setup because ssh won’t know which key to use.

check which repos need updating:

# in any repo, check the current remote
git remote -v
# origin  git@github.com:username/repo.git  ← needs to be updated

fix it by replacing github.com with your alias:

git remote set-url origin git@github.com-personal:username/repo.git

if you have many repos to migrate, you can ask llms to write a script for you ;)


tests (trust but verify)

test ssh connections:

ssh -T git@github.com-personal
# Hi <username>! You've successfully authenticated.

ssh -T git@github.com-company-a
# Hi <company-a-username>! You've successfully authenticated.

test git identity in a repo:

cd ~/Projects/Personal/some-repo
git config user.email
# personal@email.com ✓

cd ~/Projects/Company-A/some-repo
git config user.email
# work@companya.com ✓

debug (when things break)

# check loaded keys
ssh-add -l

# verbose ssh (shows which key is used)
ssh -vT git@github.com-personal

# check remote url
git remote -v

# check current identity
git config user.email

rules (the mindset)

  • no generic ssh key names (id_ed25519)
  • never use github.com directly in multi-account setups
  • never rely on ssh agent “guessing” the right key
  • explicit aliases for every account
  • conditional git config by folder
  • keychain persistence (macOS)

in a nutshell, this setup:

  • scales (add clients, companies, oss accounts)
  • survives reboots
  • eliminates 100% of identity errors
  • is documentable, auditable, reproducible

once i configured it, i stopped worrying about git. that’s the point.