GIT MULTI-ACCOUNT
PERSONAL MANUAL

Managing two GitHub accounts on macOS without the headache. Authentication, authorship, and the full setup, in one place.

maintained by Rehan Ahmed last updated 2026.04.27 tested on macOS

The Mental Model

Two things are configured independently for every git operation:

  1. Authentication — who is allowed to push, decided by the SSH key that loads based on the remote URL's host alias.
  2. Authorship — whose name appears on the commit, decided by user.email set inside the repo.

These two should always match, but git won't enforce that. The setup here makes them behave like one decision, so mistakes are hard to make.

The two SSH host aliases

Instead of using github.com directly, use one of these aliases as the host in remote URLs:

Both resolve to github.com, but each loads a different SSH key, telling GitHub which account is acting.

Daily Workflow

Cloning an existing repo

Decide which account owns the repo, then clone with the matching alias.

REHANAMD repo:

bash
git clone git@github.com-rehanamd:REHANAMD/repo-name.git
cd repo-name
git config user.email "somanirehan8@gmail.com"

rehanahmed1803 repo:

bash
git clone git@github.com-1803:rehanahmed1803/repo-name.git
cd repo-name
git config user.email "rehanamesomani@gmail.com"
→ tip
user.name can be skipped — GitHub identifies commits by email only. But setting it makes git log cleaner, so it's a good habit.

Starting a new local project and pushing it

  1. Create the repo on github.com first (logged in as the right account). Don't initialize with a README.
  2. Then locally:
bash // REHANAMD project
mkdir my-project && cd my-project
git init
git config user.email "somanirehan8@gmail.com"
echo "# my-project" > README.md
git add .
git commit -m "initial commit"
git branch -M main
git remote add origin git@github.com-rehanamd:REHANAMD/my-project.git
git push -u origin main

For an rehanahmed1803 project, swap the email and the remote URL:

bash // rehanahmed1803 swap
git config user.email "rehanamesomani@gmail.com"
git remote add origin git@github.com-1803:rehanahmed1803/my-project.git

Switching an existing repo to the right account

If a repo's remote was set up the old way (HTTPS or wrong alias), reconfigure it:

bash
# Check current remote
git remote -v

# Switch to the right alias
git remote set-url origin git@github.com-1803:rehanahmed1803/repo.git

# Set the right author identity
git config user.email "rehanamesomani@gmail.com"

# Verify
git remote -v
git config --list | grep user

Routine commands (no surprises)

Once a repo is set up correctly, the everyday flow is normal git:

bash // daily
git status                    # see what changed
git add .                     # stage everything
git add file.cpp              # stage one file
git commit -m "message"       # commit
git push                      # push (origin and branch already tracked)
git pull                      # fetch + merge
git log --oneline -10         # last 10 commits, one line each
git diff                      # unstaged changes
git diff --staged             # staged changes

Branching basics

bash // branches
git branch                    # list branches
git branch new-feature        # create branch
git checkout new-feature      # switch to it
git checkout -b new-feature   # create + switch in one command
git merge feature-branch      # merge into current branch
git branch -d old-branch      # delete a merged branch
git push -u origin new-branch # push new branch and track it

Undoing things

bash // undo
git restore file.cpp                # discard unstaged changes
git restore --staged file.cpp       # unstage a file (keep changes)
git commit --amend -m "new message" # change last commit message
git reset --soft HEAD~1             # undo last commit, keep changes staged
git reset --hard HEAD~1             # NUKE last commit and changes
⚠ warning
git reset --hard is irreversible. Use it only when you're sure. If something goes wrong, git reflog can sometimes recover lost commits within a few weeks.

The .gitignore Pattern

How gitignore actually works

A .gitignore file only prevents untracked files from being added. If a file is already tracked, gitignore is silently ignored for it. To untrack an already-tracked file:

bash
git rm --cached path/to/file        # untrack but keep on disk
git rm -r --cached path/to/folder/  # untrack a folder

Then commit the change.

Recommended .gitignore for C++ projects

.gitignore
# Compiled binaries
*.out
*.exe
*.o
*.obj
*.class

# Build folder (preferred convention)
bin/
build/

# IDE / editor noise
.vscode/
.idea/
*.swp
.DS_Store

The bin/ folder convention

Compile binaries into a dedicated folder so a single line in .gitignore ignores them all:

bash
mkdir bin
g++ source.cpp -o bin/source
./bin/source

Cleanup, Diagnostics, and Recovery

Verifying which account is in use

bash // diagnostics
ssh -T git@github.com-rehanamd      # expect: Hi REHANAMD!
ssh -T git@github.com-1803          # expect: Hi rehanahmed1803!

git remote -v                       # check remote URL
git config --list | grep user       # check current author identity

If a push fails with 403 or "Permission denied"

  1. Run git remote -v. Confirm the URL uses the right alias (github.com-rehanamd or github.com-1803), not plain github.com.
  2. Run the ssh -T test for that alias. If it greets the wrong username, the SSH config is misconfigured.
  3. Check for stale credentials cached in macOS Keychain:
bash // keychain cleanup
security find-internet-password -s github.com
security delete-internet-password -s github.com

Fixing wrong-author commits

If commits were already made with the wrong author email, two options:

bash // dangerous
# Always backup first
git branch backup-before-rewrite

# Rewrite (install via: brew install git-filter-repo)
git filter-repo --commit-callback '
    if commit.author_email == b"old@email.com":
        commit.author_email = b"new@email.com"
        commit.author_name = b"NewName"
'

# Force push (destructive)
git push --force-with-lease

Stashing work in progress

bash // stash
git stash                    # save changes, clean working tree
git stash list               # see saved stashes
git stash pop                # restore most recent and remove from stash
git stash apply              # restore but keep in stash
git stash drop               # delete most recent stash

Setup on a New Mac

Full one-time setup to repeat the multi-account configuration on a fresh machine. Total time: about 10 minutes.

  1. Install git
    bash
    git --version

    If macOS prompts to install Command Line Tools, accept. Otherwise: brew install git

  2. Generate two SSH keys
    bash
    ssh-keygen -t ed25519 -C "somanirehan8@gmail.com" -f ~/.ssh/id_ed25519_rehanamd
    ssh-keygen -t ed25519 -C "rehanamesomani@gmail.com" -f ~/.ssh/id_ed25519_rehanahmed1803

    Press Enter twice at each passphrase prompt (or set one if preferred).

  3. Add public keys to GitHub

    For REHANAMD — copy key, sign in as REHANAMD, Settings → SSH and GPG keys → New SSH key → paste:

    bash
    pbcopy < ~/.ssh/id_ed25519_rehanamd.pub

    For rehanahmed1803 — sign out, sign in as rehanahmed1803, repeat:

    bash
    pbcopy < ~/.ssh/id_ed25519_rehanahmed1803.pub
  4. Configure SSH host aliases
    bash
    nano ~/.ssh/config

    Paste this into the file:

    ~/.ssh/config
    Host github.com-rehanamd
      HostName github.com
      User git
      IdentityFile ~/.ssh/id_ed25519_rehanamd
      IdentitiesOnly yes
    
    Host github.com-1803
      HostName github.com
      User git
      IdentityFile ~/.ssh/id_ed25519_rehanahmed1803
      IdentitiesOnly yes

    Save (Ctrl+O, Enter, Ctrl+X). Then secure the file:

    bash
    chmod 600 ~/.ssh/config
  5. Test both keys
    bash
    ssh -T git@github.com-rehanamd      # expect: Hi REHANAMD!
    ssh -T git@github.com-1803          # expect: Hi rehanahmed1803!

    If prompted to confirm host authenticity, type yes.

  6. Unset any global identity
    bash
    git config --global --unset user.name  || true
    git config --global --unset user.email || true

    This forces every repo to set its own identity, eliminating wrong-author mistakes.

  7. Clean any cached HTTPS credentials
    bash
    security delete-internet-password -s github.com

    Run repeatedly until it reports nothing to delete.

→ done
After this setup, every repo on the new Mac just needs the per-repo configuration shown in Section 02 (one-time, two commands). Identities and authentication are fully separated and automatic from there.

Quick-Reference Cheat Sheet

Remote URL formats

remote URLs
# REHANAMD
git@github.com-rehanamd:REHANAMD/<repo>.git

# rehanahmed1803
git@github.com-1803:rehanahmed1803/<repo>.git

Per-repo identity

bash // identity
# REHANAMD
git config user.email "somanirehan8@gmail.com"
git config user.name  "REHANAMD"

# rehanahmed1803
git config user.email "rehanamesomani@gmail.com"
git config user.name  "rehanahmed1803"

Most-used commands

bash // top 7
git status
git add . && git commit -m "msg" && git push
git pull
git checkout -b new-branch
git log --oneline --graph --all -20
git stash / git stash pop
git remote -v