DEV Community

Cover image for Never commit with the wrong Git identity again
Andrei Balaianu
Andrei Balaianu

Posted on

Never commit with the wrong Git identity again

If you have more than one GitHub account — and at this point, who doesn't — you've probably pushed a commit with the wrong email at least once. Maybe it was a personal project that went out under your work email. Maybe it was the other way around. Either way, Git didn't warn you, GitHub didn't warn you, and you found out when you looked at the commit history and saw someone who isn't quite you taking credit for the work.

And if you're like me, it's not just two identities and two repos. It's work, personal, side projects, client work, experiments you're not ready to explain — each tied to its own GitHub account, its own email, its own SSH key. The number of repos grows, the number of identities grows, and the odds of pushing under the wrong one keep going up with them.

The standard fix is to run git config user.email in each repo. That works. It also relies on you remembering to do it every single time, which — let's be honest — you're not going to do. Not consistently. Not when you're in the middle of fixing something and just want to commit and move on.

There's a better way, and it's been in Git since 2017.

includeIf: the feature you probably don't know about

Git 2.13 introduced includeIf. It lets you apply different configurations based on which directory you're in. You set it up once in your ~/.gitconfig:

[includeIf "gitdir:/home/you/dev/work/"]
    path = ~/.config/git-persona/profiles/work.gitconfig

[includeIf "gitdir:/home/you/dev/personal/"]
    path = ~/.config/git-persona/profiles/personal.gitconfig
Enter fullscreen mode Exit fullscreen mode

Now any repo under ~/dev/work/ automatically uses your work name, work email, and work SSH key. Any repo under ~/dev/personal/ uses your personal ones. No per-repo config. No remembering. No checking before every push.

Each profile config is just a regular git config file:

[user]
    name = Work Name
    email = work@example.com
[core]
    sshCommand = ssh -i ~/.ssh/id_ed25519_git_work -o IdentitiesOnly=yes
Enter fullscreen mode Exit fullscreen mode

That's it. Git does the rest. When you're in a repo under ~/dev/work/, it loads the work config. When you're in a repo under ~/dev/personal/, it loads the personal config. The switch is automatic and based on the directory path, so you don't have to think about it.

Why isn't everyone using this?

Because the manual setup is annoying. To do it by hand you need to:

  1. Generate an SSH key for each identity
  2. Create a git config file for each identity
  3. Write includeIf rules in your ~/.gitconfig with the correct path syntax — and trailing slashes matter. Without one, gitdir:/home/you/dev/work matches by prefix, so it would also apply to /home/you/dev/workplace. The slash narrows the match to repos inside that directory only.

It's not hard. It's just the kind of tedious you keep saying you'll do this weekend and then you don't.

git-persona: the 30-second version

I wrote a bash script that does all of it for you:

git persona create work "Your Name" work@example.com ~/dev/work
git persona create personal "Your Name" personal@example.com ~/dev/personal
Enter fullscreen mode Exit fullscreen mode

One command per identity. It generates the SSH key, creates the config file, writes the includeIf rule, and prints the public key so you can add it to GitHub. You clone repos into the right folder and the right identity shows up. Every time.

git persona current    # who am I in this folder?
git persona list       # what identities do I have?
git persona use work   # override for this specific repo
Enter fullscreen mode Exit fullscreen mode

No dependencies. No runtime. No daemon. It's pure bash — 600 lines, readable in 10 minutes. If a tool is managing your SSH keys, you should be able to read its source and verify it's not doing anything weird. So you can.

A few things worth knowing

The trailing slash matters. gitdir:/home/you/dev/work/ matches only repos inside that directory. gitdir:/home/you/dev/work matches by prefix, so it also catches /home/you/dev/workplace. The slash narrows the match. Get it wrong and the wrong repos get the wrong identity — silently.

Use absolute paths. Relative paths in includeIf are resolved relative to the config file's location, not your current directory. This is documented but easy to misread. git-persona resolves paths to absolute for you, but if you're setting it up manually, use full paths.

One SSH key per identity. GitHub doesn't allow the same SSH key on two accounts — it'll reject it with "Key is already in use." But if you have multiple keys loaded in your ssh-agent, SSH may offer the wrong one first, and GitHub authenticates you as whichever account owns that key. That's why git-persona sets IdentitiesOnly=yes in the sshCommand — it forces SSH to use only the key specified for that identity, ignoring whatever else is in your agent.

You can skip SSH keys. If you use HTTPS with a credential helper instead of SSH, git persona create has a --no-ssh-key flag. The profile will only set user.name and user.email.

Try it

curl -fsSL https://raw.githubusercontent.com/balaianu/git-persona/main/install.sh | bash
Enter fullscreen mode Exit fullscreen mode

Repo: github.com/balaianu/git-persona

MIT, tested on Linux/macOS/WSL, pure bash. If it saves you from one wrong-identity commit, it was worth the 30 seconds.

If you've been managing multiple Git identities manually — the per-repo config, the SSH key juggling, the "I'll set it up properly this weekend" — this is the weekend. The feature has been in Git since 2017. It'll wait for you however long you take. But you might as well do it now.

Top comments (0)