<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrei Balaianu</title>
    <description>The latest articles on DEV Community by Andrei Balaianu (@balaianu).</description>
    <link>https://dev.to/balaianu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F146991%2Fbc98fcf4-3376-4e47-9631-f346119610cf.jpeg</url>
      <title>DEV Community: Andrei Balaianu</title>
      <link>https://dev.to/balaianu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/balaianu"/>
    <language>en</language>
    <item>
      <title>Never commit with the wrong Git identity again</title>
      <dc:creator>Andrei Balaianu</dc:creator>
      <pubDate>Thu, 20 Aug 2026 09:00:00 +0000</pubDate>
      <link>https://dev.to/balaianu/never-commit-with-the-wrong-git-identity-again-4785</link>
      <guid>https://dev.to/balaianu/never-commit-with-the-wrong-git-identity-again-4785</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The standard fix is to run &lt;code&gt;git config user.email&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;There's a better way, and it's been in Git since 2017.&lt;/p&gt;

&lt;h2&gt;
  
  
  includeIf: the feature you probably don't know about
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[includeIf "gitdir:/home/you/dev/work/"]&lt;/span&gt;
    &lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;~/.config/git-persona/profiles/work.gitconfig&lt;/span&gt;

&lt;span class="nn"&gt;[includeIf "gitdir:/home/you/dev/personal/"]&lt;/span&gt;
    &lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;~/.config/git-persona/profiles/personal.gitconfig&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Each profile config is just a regular git config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[user]&lt;/span&gt;
    &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Work Name&lt;/span&gt;
    &lt;span class="py"&gt;email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;work@example.com&lt;/span&gt;
&lt;span class="nn"&gt;[core]&lt;/span&gt;
    &lt;span class="py"&gt;sshCommand&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ssh -i ~/.ssh/id_ed25519_git_work -o IdentitiesOnly=yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h2&gt;
  
  
  Why isn't everyone using this?
&lt;/h2&gt;

&lt;p&gt;Because the manual setup is annoying. To do it by hand you need to:&lt;/p&gt;

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

&lt;p&gt;It's not hard. It's just the kind of tedious you keep saying you'll do this weekend and then you don't.&lt;/p&gt;

&lt;h2&gt;
  
  
  git-persona: the 30-second version
&lt;/h2&gt;

&lt;p&gt;I wrote a bash script that does all of it for you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git persona create work &lt;span class="s2"&gt;"Your Name"&lt;/span&gt; work@example.com ~/dev/work
git persona create personal &lt;span class="s2"&gt;"Your Name"&lt;/span&gt; personal@example.com ~/dev/personal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One command per identity. It generates the SSH key, creates the config file, writes the &lt;code&gt;includeIf&lt;/code&gt; 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.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git persona current    &lt;span class="c"&gt;# who am I in this folder?&lt;/span&gt;
git persona list       &lt;span class="c"&gt;# what identities do I have?&lt;/span&gt;
git persona use work   &lt;span class="c"&gt;# override for this specific repo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few things worth knowing
&lt;/h2&gt;

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

&lt;p&gt;&lt;strong&gt;Use absolute paths.&lt;/strong&gt; Relative paths in &lt;code&gt;includeIf&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One SSH key per identity.&lt;/strong&gt; 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 &lt;code&gt;IdentitiesOnly=yes&lt;/code&gt; in the sshCommand — it forces SSH to use only the key specified for that identity, ignoring whatever else is in your agent.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/balaianu/git-persona/main/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo: &lt;a href="https://github.com/balaianu/git-persona" rel="noopener noreferrer"&gt;github.com/balaianu/git-persona&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;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.&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>productivity</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
