Table of Contents
Open Table of Contents
Overview
Managing multiple GitHub accounts (personal, work, client projects) on a single machine can be challenging. This guide provides a complete solution using SSH keys, Git configuration, and URL rewriting to seamlessly switch between accounts without constant authentication hassles.
Architecture Overview
graph TB
subgraph "Local Machine"
A[Git Client]
B[SSH Agent]
C[SSH Config]
D[Git Config]
end
subgraph "SSH Keys"
E[Personal Key]
F[Work Key]
G[Client Key]
end
subgraph "GitHub Accounts"
H[Personal Account]
I[Work Account]
J[Client Account]
end
A --> B
B --> C
C --> E
C --> F
C --> G
E --> H
F --> I
G --> J
D --> A
style A fill:#4ecdc4,stroke:#087f5b,stroke-width:2px
style B fill:#74c0fc,stroke:#1971c2,stroke-width:2px
style C fill:#ffd43b,stroke:#fab005,stroke-width:2px
SSH Key Setup
Generate SSH Keys for Each Account
# Generate SSH key for personal account
ssh-keygen -t ed25519 -C "personal@email.com" -f ~/.ssh/id_ed25519_personal
# Generate SSH key for work account
ssh-keygen -t ed25519 -C "work@company.com" -f ~/.ssh/id_ed25519_work
# Generate SSH key for client account
ssh-keygen -t ed25519 -C "contractor@client.com" -f ~/.ssh/id_ed25519_client
# List generated keys
ls -la ~/.ssh/id_ed25519_*
Add SSH Keys to SSH Agent
# Start SSH agent
eval "$(ssh-agent -s)"
# Add keys to SSH agent
ssh-add ~/.ssh/id_ed25519_personal
ssh-add ~/.ssh/id_ed25519_work
ssh-add ~/.ssh/id_ed25519_client
# Verify keys are loaded
ssh-add -l
SSH Configuration
Configure SSH Hosts
Create or edit ~/.ssh/config
:
# Personal GitHub account
Host github.com-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
IdentitiesOnly yes
# Work GitHub account
Host github.com-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
# Client GitHub account
Host github.com-client
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_client
IdentitiesOnly yes
# Default GitHub (optional)
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
IdentitiesOnly yes
Set Correct Permissions
# Set correct permissions for SSH directory and files
chmod 700 ~/.ssh
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/id_ed25519_*
chmod 644 ~/.ssh/id_ed25519_*.pub
Adding Keys to GitHub
Add SSH Keys to GitHub Accounts
# Copy public key to clipboard (macOS)
pbcopy < ~/.ssh/id_ed25519_personal.pub
# Copy public key to clipboard (Linux)
xclip -sel clip < ~/.ssh/id_ed25519_personal.pub
# Or display key to copy manually
cat ~/.ssh/id_ed25519_personal.pub
Then add each key to the respective GitHub account:
- Go to GitHub → Settings → SSH and GPG keys
- Click “New SSH key”
- Paste the public key
- Give it a descriptive title
Test SSH Connections
# Test personal account
ssh -T git@github.com-personal
# Test work account
ssh -T git@github.com-work
# Test client account
ssh -T git@github.com-client
Git Configuration Strategy
Directory-Based Configuration
graph TD
A[Git Configuration Strategy] --> B[Global Config]
A --> C[Directory-Based Config]
A --> D[Repository Config]
B --> E[Default Identity]
C --> F[Conditional Includes]
D --> G[Override per Repo]
F --> H[Personal Projects]
F --> I[Work Projects]
F --> J[Client Projects]
style A fill:#4ecdc4,stroke:#087f5b,stroke-width:2px
style C fill:#74c0fc,stroke:#1971c2,stroke-width:2px
style F fill:#ffd43b,stroke:#fab005,stroke-width:2px
Global Git Configuration
Edit ~/.gitconfig
:
[user]
name = Your Name
email = personal@email.com # Default email
[includeIf "gitdir:~/personal/"]
path = ~/.gitconfig-personal
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
[includeIf "gitdir:~/client/"]
path = ~/.gitconfig-client
[url "git@github.com-personal:"]
insteadOf = https://github.com/
[url "git@github.com-work:"]
pushInsteadOf = https://github.com/work-org/
[url "git@github.com-client:"]
pushInsteadOf = https://github.com/client-org/
Account-Specific Git Configs
Create ~/.gitconfig-personal
:
[user]
name = Personal Name
email = personal@email.com
[github]
user = personal-username
Create ~/.gitconfig-work
:
[user]
name = Work Name
email = work@company.com
[github]
user = work-username
[core]
sshCommand = ssh -i ~/.ssh/id_ed25519_work
Create ~/.gitconfig-client
:
[user]
name = Contractor Name
email = contractor@client.com
[github]
user = client-username
[core]
sshCommand = ssh -i ~/.ssh/id_ed25519_client
Repository Management
Cloning Repositories
# Clone personal repository
git clone git@github.com-personal:username/personal-repo.git
# Clone work repository
git clone git@github.com-work:work-org/work-repo.git
# Clone client repository
git clone git@github.com-client:client-org/client-repo.git
Setting Remote URLs
# For existing repositories, update remote URL
cd existing-repo
# For personal account
git remote set-url origin git@github.com-personal:username/repo.git
# For work account
git remote set-url origin git@github.com-work:work-org/repo.git
# Verify remote URL
git remote -v
Automation Scripts
Account Switching Script
Create ~/bin/git-switch-account
:
#!/bin/bash
# git-switch-account - Switch between GitHub accounts
show_usage() {
echo "Usage: git-switch-account [personal|work|client]"
echo " git-switch-account status"
exit 1
}
check_git_repo() {
if ! git rev-parse --git-dir > /dev/null 2>&1; then
echo "Error: Not in a git repository"
exit 1
fi
}
show_status() {
echo "Current Git Configuration:"
echo "Name: $(git config user.name)"
echo "Email: $(git config user.email)"
echo ""
echo "Remote URLs:"
git remote -v
}
switch_account() {
local account=$1
check_git_repo
case $account in
personal)
git config user.name "Personal Name"
git config user.email "personal@email.com"
echo "Switched to personal account"
;;
work)
git config user.name "Work Name"
git config user.email "work@company.com"
echo "Switched to work account"
;;
client)
git config user.name "Contractor Name"
git config user.email "contractor@client.com"
echo "Switched to client account"
;;
*)
show_usage
;;
esac
show_status
}
# Main script
case "${1:-}" in
status)
check_git_repo
show_status
;;
personal|work|client)
switch_account "$1"
;;
*)
show_usage
;;
esac
Make the script executable:
chmod +x ~/bin/git-switch-account
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
Repository Setup Script
Create ~/bin/git-setup-repo
:
#!/bin/bash
# git-setup-repo - Setup repository with correct account
if [ $# -ne 2 ]; then
echo "Usage: git-setup-repo [personal|work|client] <repo-url>"
exit 1
fi
ACCOUNT=$1
REPO_URL=$2
REPO_NAME=$(basename "$REPO_URL" .git)
# Determine the correct host
case $ACCOUNT in
personal)
HOST="github.com-personal"
;;
work)
HOST="github.com-work"
;;
client)
HOST="github.com-client"
;;
*)
echo "Invalid account: $ACCOUNT"
exit 1
;;
esac
# Clone the repository
MODIFIED_URL=$(echo "$REPO_URL" | sed "s/github.com/$HOST/g")
git clone "$MODIFIED_URL" "$REPO_NAME"
# Configure the repository
cd "$REPO_NAME"
git-switch-account "$ACCOUNT"
echo "Repository $REPO_NAME setup complete for $ACCOUNT account"
Best Practices
Security Workflow
graph TD
A[Security Best Practices] --> B[Key Management]
A --> C[Access Control]
A --> D[Audit Trail]
B --> E[Unique Keys per Account]
B --> F[Strong Passphrases]
B --> G[Regular Key Rotation]
C --> H[Repository Permissions]
C --> I[2FA Enforcement]
C --> J[IP Whitelisting]
D --> K[Commit Signing]
D --> L[Activity Monitoring]
style A fill:#ff6b6b,stroke:#c92a2a,stroke-width:2px
style B fill:#74c0fc,stroke:#1971c2,stroke-width:2px
style K fill:#4ecdc4,stroke:#087f5b,stroke-width:2px
Commit Signing Setup
# Generate GPG key for each account
gpg --full-generate-key
# List GPG keys
gpg --list-secret-keys --keyid-format=long
# Configure Git to use GPG key
git config --global user.signingkey <key-id>
git config --global commit.gpgsign true
# Add GPG key to GitHub account
gpg --armor --export <key-id>
SSH Key Rotation
#!/bin/bash
# rotate-ssh-keys.sh - Rotate SSH keys for security
ACCOUNTS=("personal" "work" "client")
BACKUP_DIR="$HOME/.ssh/backup-$(date +%Y%m%d)"
# Backup existing keys
mkdir -p "$BACKUP_DIR"
cp ~/.ssh/id_ed25519_* "$BACKUP_DIR/"
# Generate new keys
for account in "${ACCOUNTS[@]}"; do
echo "Rotating key for $account account..."
# Generate new key
ssh-keygen -t ed25519 -C "$account@email.com" \
-f "$HOME/.ssh/id_ed25519_${account}_new" -N ""
# Replace old key
mv "$HOME/.ssh/id_ed25519_${account}_new" \
"$HOME/.ssh/id_ed25519_${account}"
mv "$HOME/.ssh/id_ed25519_${account}_new.pub" \
"$HOME/.ssh/id_ed25519_${account}.pub"
done
echo "Keys rotated. Backup stored in: $BACKUP_DIR"
echo "Remember to update GitHub with new public keys!"
Troubleshooting
Common Issues and Solutions
-
Permission Denied (publickey)
# Check SSH agent ssh-add -l # Re-add keys if needed ssh-add ~/.ssh/id_ed25519_personal # Verify SSH config ssh -vT git@github.com-personal
-
Wrong Account Pushing
# Check current configuration git config user.email git config user.name # Verify remote URL git remote -v # Fix remote URL if needed git remote set-url origin git@github.com-work:org/repo.git
-
SSH Key Not Found
# Check key permissions ls -la ~/.ssh/ # Fix permissions chmod 600 ~/.ssh/id_ed25519_* chmod 644 ~/.ssh/id_ed25519_*.pub
Debugging SSH Connections
# Verbose SSH test
ssh -vvv git@github.com-personal
# Check SSH config syntax
ssh -G git@github.com-personal
# Test specific identity file
ssh -i ~/.ssh/id_ed25519_personal -T git@github.com
Advanced Configuration
URL Rewriting for Organizations
# ~/.gitconfig
# Automatically use work account for work organization
[url "git@github.com-work:work-org/"]
insteadOf = https://github.com/work-org/
insteadOf = git@github.com:work-org/
# Automatically use client account for client organization
[url "git@github.com-client:client-org/"]
insteadOf = https://github.com/client-org/
insteadOf = git@github.com:client-org/
Automated Account Detection
#!/bin/bash
# ~/.config/git/hooks/pre-commit
# Automatically set identity based on remote URL
REMOTE_URL=$(git config --get remote.origin.url)
if [[ $REMOTE_URL == *"work-org"* ]]; then
git config user.name "Work Name"
git config user.email "work@company.com"
elif [[ $REMOTE_URL == *"client-org"* ]]; then
git config user.name "Contractor Name"
git config user.email "contractor@client.com"
else
git config user.name "Personal Name"
git config user.email "personal@email.com"
fi
Integration with Development Tools
VS Code Configuration
// .vscode/settings.json for workspace
{
"git.path": "/usr/bin/git",
"terminal.integrated.env.linux": {
"GIT_SSH_COMMAND": "ssh -i ~/.ssh/id_ed25519_work"
},
"terminal.integrated.env.osx": {
"GIT_SSH_COMMAND": "ssh -i ~/.ssh/id_ed25519_work"
}
}
Shell Aliases
# ~/.bashrc or ~/.zshrc
alias git-personal='GIT_SSH_COMMAND="ssh -i ~/.ssh/id_ed25519_personal" git'
alias git-work='GIT_SSH_COMMAND="ssh -i ~/.ssh/id_ed25519_work" git'
alias git-client='GIT_SSH_COMMAND="ssh -i ~/.ssh/id_ed25519_client" git'
# Quick clone aliases
alias gcp='git clone git@github.com-personal:'
alias gcw='git clone git@github.com-work:'
alias gcc='git clone git@github.com-client:'
Conclusion
Managing multiple GitHub accounts on a single machine is straightforward with proper SSH configuration and Git setup. This approach provides:
- Clear separation between personal, work, and client projects
- Automatic identity switching based on project location
- Secure authentication using SSH keys
- Flexibility to add more accounts as needed
Key takeaways:
- Use separate SSH keys for each GitHub account
- Configure SSH hosts to differentiate accounts
- Leverage Git’s conditional includes for automatic configuration
- Use URL rewriting for seamless integration
- Implement scripts for common operations
- Maintain security through key rotation and commit signing
With this setup, you can effortlessly work with multiple GitHub accounts without authentication conflicts or identity confusion.