Connecting to Git Repositories with Multiple Identities
Working with more than one Git account on a single machine is common for an engineer — there’s a personal account for open source and side projects, a work account for the main job, and sometimes an organization or client account for specific projects. If not set up properly, this situation brings up classic problems: commits using the wrong email, pushing to a repository with the wrong account, or confusing SSH authentication errors because Git tries the wrong key. This article discusses the correct, clean, and scalable way to connect many Git repositories with different identities on one computer.
Basic Principles
The biggest source of confusion in managing multiple Git identities is mixing up two things that are actually different: authentication to the Git server and commit identity. Authentication to the Git server — the process determining whether you have access rights to a repository — is handled via SSH keys. Commit identity — the name and email recorded in every commit you make — is handled via user.name and user.email in Git configuration.
Both must be explicitly separated. The SSH key determines who is allowed in, while user.name and user.email determine on whose behalf the commit is made. One of the most common bug sources is assuming that the correct SSH key automatically means the commit identity is also correct — even though the two are configured separately and don’t affect each other.
This confusion often appears because on the surface, both feel like “the same thing” — after all, they both relate to the same Git account. But technically, the SSH key works at the transport layer when Git communicates with the server ([email protected]), while user.name and user.email are just plain text metadata written into the commit object itself. You could be properly authenticated via your work account’s SSH key, yet still make commits with your personal email — Git won’t validate or match the two automatically.
| Aspect | SSH Key | user.name / user.email |
|---|---|---|
| Function | Authentication to the Git server | Commit identity metadata |
| Config location | ~/.ssh/config and ~/.ssh/ | .git/config per repository |
| Impact if wrong | Push rejected or wrong repo access | Commits recorded with the wrong identity |
| Where it’s visible | Server auth logs (GitHub, etc.) | Commit history (git log) |
flowchart TD
A[Git Operation] --> B{Push / Pull / Clone}
B --> C[SSH Key: Authentication to the server]
A --> D{Commit}
D --> E[user.name + user.email: Commit identity]
C -.->|Not automatically connected| ECreate a Separate SSH Key for Each Identity
Never use the same SSH key for all accounts. One key used across many accounts makes auditing difficult — if that key leaks, you must revoke access on all accounts at once, not just one. Create a separate SSH key for each identity:
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_personal
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_work
The -t ed25519 flag selects the Ed25519 algorithm, which is faster and more secure than RSA for the same key size. The -C flag adds a comment (usually an email) for easier key identification when viewing the key list registered on a Git account. The -f flag determines the output path and file name, so the two keys don’t overwrite the default id_ed25519.
After the keys are created, add the public key (.pub) to the matching Git account — GitHub, GitLab, or Bitbucket usually have a dedicated “SSH Keys” menu on the account settings page.
The private key (the file without the.pubextension, e.g.id_ed25519_personal) must never be shared with anyone and must never be committed to any repository. Only the public key (id_ed25519_personal.pub) is safe to share and register with the Git server.
Configuring ~/.ssh/config
After the two SSH keys are created, SSH still doesn’t know which key to use for which connection to github.com — because by default all keys will be tried one by one. To fix this, use host aliases in the ~/.ssh/config file:
# Personal account
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
IdentitiesOnly yes
# Work account
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
Each Host block defines a new alias. HostName specifies the actual domain being targeted (in this case, both remain github.com), while Host on the first line is the alias name you use yourself when running Git commands — not a domain name that must match anything on the server side. IdentityFile points to the matching private key, and IdentitiesOnly yes tells SSH to only try the explicitly mentioned key, not every key in ~/.ssh/.
With this configuration, SSH won’t guess which key to use — each alias is explicitly connected to one specific key.
Use the Host Alias in Git Remotes
The SSH configuration above only truly works if the repository’s remote URL uses the host alias, not the original github.com domain directly. This is the most often missed step — many people already create the SSH keys and ~/.ssh/config correctly, but still use the default remote URL pointing to github.com without the alias.
Cloning a Repository
# Personal repo
git clone git@github-personal:username/personal-repo.git
# Work repo
git clone git@github-work:company/work-repo.git
Notice the part after git@ — here the host alias (github-personal or github-work) replaces github.com. SSH reads this alias, matches it against the ~/.ssh/config configuration, then automatically uses the matching IdentityFile without needing to specify the key manually every time.
Changing an Existing Remote
For repositories that already exist and still use the default URL, change the remote with:
git remote set-url origin git@github-work:company/work-repo.git
After the remote is changed, every push, pull, or fetch operation in that repository will automatically use the SSH key connected to the github-work alias.
Set Commit Identity Per Repository
The SSH key only manages access rights — who can push where — not the identity recorded in commits. Commit identity must be configured separately, and ideally per repository, not globally. Enter each repository, then run:
git config user.name "Personal Name"
git config user.email "[email protected]"
For the work repository, enter its directory and run a different configuration:
git config user.name "Work Name"
git config user.email "[email protected]"
Without the --global flag, the git config commands above only apply to the currently active repository (stored in that repository’s .git/config file), not to every repository on the machine. This is the key — each repository has its own commit identity, regardless of whatever global configuration exists.
Avoid relying on git config --global user.email if you frequently switch work contexts. The global configuration is only a fallback used when a repository doesn’t have its own local configuration — if you forget to set the local identity in one repository, commits will automatically use the global identity, which is often not the one that should be used.Automation with includeIf Based on Directories
Setting user.name and user.email manually in every new repository can be tedious, especially if you often clone new repositories for one particular work context. Git provides includeIf, which allows configuration to be applied automatically based on the repository’s directory location — this approach is very useful if you consistently put all work repositories in one folder, and personal repositories in another.
First, create a separate configuration file for each context:
# ~/.gitconfig-personal
[user]
name = Personal Name
email = [email protected]
# ~/.gitconfig-work
[user]
name = Work Name
email = [email protected]
Then, in the main ~/.gitconfig, add includeIf blocks pointing to each file based on the directory path:
# ~/.gitconfig
[includeIf "gitdir:~/projects/personal/"]
path = ~/.gitconfig-personal
[includeIf "gitdir:~/projects/work/"]
path = ~/.gitconfig-work
With this configuration, every repository inside ~/projects/personal/ automatically uses the identity from ~/.gitconfig-personal, and repositories in ~/projects/work/ automatically use the identity from ~/.gitconfig-work — without needing to run git config user.email manually every time you clone a new repository in those directories.
Make sure the path in gitdir: ends with a / so Git matches all repositories inside that directory, not just one exact path. A consistent folder structure — for example all work repos always under one particular folder — is a prerequisite for this approach to work well.
Common Mistakes to Avoid
✗ One SSH key used for all accounts
-- makes auditing difficult, security risk, prone to wrong access
✗ Relying on git config --global user.email as the only identity source
-- the main cause of commits with the wrong identity
✗ Not using IdentitiesOnly yes in the SSH config
-- SSH tries all available keys, triggering Permission denied (publickey) errors
These three mistakes are interconnected. One SSH key for all accounts usually appears because of a rushed initial setup — faster to use an existing key than to create a new key for each account. Relying on a global user.email appears because it feels more practical at first, yet it actually makes commit identity mistakes easy once you start working across more than one repository with different contexts. Meanwhile, without IdentitiesOnly yes, SSH will try all keys in ~/.ssh/ in sequence until one matches or the server rejects all of them — this process often produces a confusing Permission denied (publickey) error, even though the correct key actually exists, it just wasn’t tried first or the trial order was wrong.
The same pattern applies to the habit of postponing proper setup. Many engineers only realize the importance of separating identities after a wrong-account commit has already been pushed to a public or work repository — a moment that’s usually embarrassing and sometimes hard to fix without rewriting commit history. Investing ten minutes at the start on SSH key setup, host aliases, and per-repository commit identities is far cheaper than fixing commit history with wrong identities, especially if those commits have already been shared with teammates through pull or fetch.
Verifying the Setup
After all the configuration above is done, verify before actually starting work. Check the SSH connection for each alias:
ssh -T github-personal
ssh -T github-work
The -T flag disables pseudo-terminal allocation, because the goal is only testing authentication, not opening an interactive session. If successful, GitHub (or another Git platform) will respond with a message confirming the authenticated username for each alias — usually a short message like “Hi username! You’ve successfully authenticated” followed by a note that GitHub doesn’t provide interactive shell access.
Also check the commit identity in the currently active repository:
git config user.name
git config user.email
Run these two commands in every relevant repository to make sure user.name and user.email already match the identity that should be used in that repository. If the result is empty, the repository doesn’t have local configuration yet and will fall back to the global configuration — which means it needs to be reset according to that repository’s context.
As an additional verification step, you can also check the latest commit to make sure the recorded identity is correct, before it gets pushed:
git log -1 --format="%an <%ae>"
This command displays the name and email of the most recent commit on the currently active branch. If the result doesn’t match the expected identity, you can still fix it with git commit --amend --author="Correct Name <[email protected]>" before that commit is pushed to the remote.
If everything is correct, Git will work without identity conflicts — pushes will land with the right account, and commits will be recorded with the name and email matching the work context.
Summary
- SSH keys and commit identities are two different things — SSH keys manage access rights,
user.name/user.emailmanage commit identity.- Create a separate SSH key for each account, never share one key across all identities.
- Use host aliases in
~/.ssh/configwithIdentitiesOnly yesso SSH doesn’t guess which key to use.- Remote URLs must use the host alias, not the default domain — this is the most often missed step.
- Set
user.nameanduser.emailper repository (without--global), don’t rely on the global configuration as the only identity source.- Verify the setup with
ssh -T <alias>for authentication andgit config user.emailfor commit identity, before starting work.- Proper setup from the start eliminates the classic wrong-account commit problems and
Permission denied (publickey)errors.