Back to blog
ProductivityGitGitHub

Set Up Multiple Git Profile on the Same Machine

A one-time SSH and Git configuration that lets your work and personal GitHub accounts coexist on the same machine without ever switching between them.

Durgesh Chaudhary
Durgesh
June 27, 2026 4 min read
Set Up Multiple Git Profile on the Same Machine

If you use the same machine for work and personal development, you've probably run into at least one of these:

  • Git commits have the wrong author email.
  • git push authenticates using the wrong GitHub account.
  • You keep logging in and out of VS Code.

This guide walks through a one-time setup that lets both accounts coexist peacefully — the right commit author, the right SSH key, the right remote — all based on where the repository lives on your machine.

Folder structure

The entire setup hinges on keeping work and personal repositories in separate folders:

~/Documents/Code/GitHub/
├── Work/
└── Personal/

This isn't just for organization. Git has a feature called includeIf that applies different configuration files depending on the directory a repository is in. By keeping repositories separated this way, Git can automatically use the correct name, email, and SSH key without you doing anything per-repository.

Step 1: Create two SSH keys

Generate one key per account, giving each a descriptive filename:

ssh-keygen -t ed25519 -C "your-work@email.com" -f ~/.ssh/github_work
ssh-keygen -t ed25519 -C "your-personal@email.com" -f ~/.ssh/github_personal

This creates two key pairs. To add them to GitHub, you first need to copy the public key contents. Run the following for each key:

cat ~/.ssh/github_work.pub
cat ~/.ssh/github_personal.pub

Or copy directly to your clipboard without printing it:

# macOS
pbcopy < ~/.ssh/github_work.pub
 
# Linux (requires xclip)
xclip -selection clipboard < ~/.ssh/github_work.pub
 
# Windows (Git Bash)
cat ~/.ssh/github_work.pub | clip

Paste the copied key into the corresponding GitHub account under Settings → SSH and GPG Keys, choosing Authentication as the key type. Repeat for the personal key on your personal account.

Why ed25519?

You might notice the generated key starts with ssh-ed25519 rather than the older ssh-rsa. That's expected — ed25519 is the recommended modern algorithm, and GitHub supports it fully.

Step 2: Configure SSH

Create (or append to) ~/.ssh/config with two host entries — one per account:

Host github-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_work
    IdentitiesOnly yes
 
Host github-personal
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_personal
    IdentitiesOnly yes

Each Host entry defines a custom alias (github-work, github-personal) that maps to github.com but uses a different SSH key. The IdentitiesOnly yes line is important — it tells SSH to only try the specified key and not fall back to any other identity in your agent.

Verify both connections work:

ssh -T git@github-work
ssh -T git@github-personal

Each should print a success message with the corresponding GitHub username.

Step 3: Configure Git identities

Create two separate Git config files — one per identity:

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

Then reference them from your main ~/.gitconfig using includeIf:

[includeIf "gitdir:~/Documents/Code/GitHub/Work/"]
    path = ~/.gitconfig-work
 
[includeIf "gitdir:~/Documents/Code/GitHub/Personal/"]
    path = ~/.gitconfig-personal

From this point on, any repository inside the Work folder automatically uses the work name and email, and any repository inside Personal uses the personal ones. You never need to run git config user.email inside individual repositories again.

Step 4: Update existing remotes to SSH

For any repositories you already have cloned, update their remotes to use the correct SSH host alias:

# For a work repository (replace "acme" with your company's GitHub org or username)
git remote set-url origin git@github-work:acme/my-project.git
 
# For a personal repository (replace "john" with your personal GitHub username)
git remote set-url origin git@github-personal:john/my-project.git

For new repositories, clone them using SSH from the start. The SSH URL format is always:

git@<ssh-host-alias>:<github-username-or-org>/<repository>.git

Note the colon after the host alias and the slash between the owner and repository name — those aren't interchangeable.

Step 5: Make cloning effortless with shell functions

At this point everything works correctly, but cloning still requires remembering the full SSH URL and the right folder to cd into. A shell function can handle all of that automatically.

The basic version

Here's a straightforward function for cloning work repositories. Add this to your ~/.zshrc or ~/.bashrc:

 
clone-work() {
    # Always clone into the Work folder regardless of where you run this from
    cd ~/Documents/Code/GitHub/Work
 
    # Clone using the github-work SSH host alias configured in Step 2
    # Replace "acme" with your actual work GitHub username or org name
    git clone git@github-work:acme/$1.git
 
    # Jump into the cloned folder
    cd $1
}
 
clone-personal() {
    cd ~/Documents/Code/GitHub/Personal
 
    # Replace "john" with your actual personal GitHub username
    git clone git@github-personal:john/$1.git
 
    cd $1
}

Now instead of typing the full SSH URL and navigating folders manually, you just run:

clone-work my-project
clone-personal my-blog

The upgraded version

The basic version works, but it will error out if you run it on a repository you've already cloned. The upgraded version handles that gracefully — and also opens VS Code automatically once you're in the folder.

 
clone-work() {
    local ROOT="$HOME/Documents/Code/GitHub/Work"
 
    # Show usage hint if no repo name is passed
    [ -z "$1" ] && { echo "Usage: clone-work <repo-name>"; return 1; }
 
    cd "$ROOT" || return
 
    # If the folder already exists locally, skip cloning
    if [ -d "$1" ]; then
        echo "📂 Opening existing repository..."
    else
        echo "⬇️  Cloning repository..."
        git clone git@github-work:acme/$1.git || return
    fi
 
    cd "$1" || return
 
    # Optional: remove this line if you don't use VS Code
    code .
}
 
clone-personal() {
    local ROOT="$HOME/Documents/Code/GitHub/Personal"
 
    [ -z "$1" ] && { echo "Usage: clone-personal <repo-name>"; return 1; }
 
    cd "$ROOT" || return
 
    if [ -d "$1" ]; then
        echo "📂 Opening existing repository..."
    else
        echo "⬇️  Cloning repository..."
        git clone git@github-personal:john/$1.git || return
    fi
 
    cd "$1" || return
 
    # Optional: remove this line if you don't use VS Code
    code .
}

Shortening to two-letter aliases (optional)

Once you're comfortable with the functions, you can rename them to shorter aliases. There's nothing special about the names — just pick whatever feels natural:

 
# Rename the functions above from clone-work/clone-personal to gw/gp
gw() { clone-work "$@"; }
gp() { clone-personal "$@"; }

Or just rename the functions themselves directly to gw and gp in the definition. The final daily usage becomes:

gw api-service    # clone (or open) a work repository
gp portfolio      # clone (or open) a personal repository

Both commands work from anywhere in your terminal — they always navigate to the correct root folder before doing anything.

After editing your ~/.zshrc or ~/.bashrc, reload it to apply the changes:

source ~/.zshrc   # or source ~/.bashrc

Step 6: Add a global pre-push hook

The setup is solid now, but one last thing worth adding is a safety net: a global Git hook that checks you're not pushing to the wrong account before every push.

First, create a global hooks directory and point Git to it:

mkdir -p ~/.githooks
git config --global core.hooksPath ~/.githooks

Then create the hook file and make it executable:

touch ~/.githooks/pre-push
chmod +x ~/.githooks/pre-push

Add the following to ~/.githooks/pre-push:

#!/bin/bash
 
REMOTE_URL=$(git remote get-url origin 2>/dev/null)
REPO_PATH=$(git rev-parse --show-toplevel 2>/dev/null)
 
WORK_DIR="$HOME/Documents/Code/GitHub/Work"
PERSONAL_DIR="$HOME/Documents/Code/GitHub/Personal"
 
# If we're in a Work folder, make sure the remote uses the work SSH host
if [[ "$REPO_PATH" == "$WORK_DIR"* ]]; then
    if [[ "$REMOTE_URL" != *"github-work"* ]]; then
        echo "❌ Error: Pushing from a Work repository but remote is not using github-work."
        echo "   Remote URL: $REMOTE_URL"
        echo "   Run: git remote set-url origin git@github-work:<org>/<repo>.git"
        exit 1
    fi
fi
 
# If we're in a Personal folder, make sure the remote uses the personal SSH host
if [[ "$REPO_PATH" == "$PERSONAL_DIR"* ]]; then
    if [[ "$REMOTE_URL" != *"github-personal"* ]]; then
        echo "❌ Error: Pushing from a Personal repository but remote is not using github-personal."
        echo "   Remote URL: $REMOTE_URL"
        echo "   Run: git remote set-url origin git@github-personal:<username>/<repo>.git"
        exit 1
    fi
fi
 
exit 0

This hook runs before every git push. It checks whether the remote URL of the repository matches the folder it lives in — if a repository inside Work is trying to push to a github-personal remote (or vice versa), the push is aborted with a clear error message telling you exactly how to fix it.

This catches the one scenario the folder-based setup can't prevent on its own: a remote URL that was manually set to the wrong account.

The final workflow

Once this is all in place, the daily workflow looks like this:

gw api-service    # clone (or open) a work repository
gp portfolio      # clone (or open) a personal repository

No account switching. No correcting commit emails after the fact. No logging in and out of VS Code. The right identity and the right SSH key are used automatically, everywhere, based entirely on where the repository lives.

Tags:GitGitHub
Share: Twitter LinkedIn