Claude
Skills
Sign in
Back

git-identity

Included with Lifetime
$97 forever

Multi-identity Git configuration with directory-scoped isolation. Sets up per-directory user email, GPG signing keys, and SSH keys using includeIf conditional includes. Use when configuring work vs personal Git identities, fixing "Unverified" commits from email/GPG key mismatch, setting up multiple GitHub accounts on one machine, auditing identity isolation, or troubleshooting includeIf, GPG key selection, or SSH key routing issues.

Productivity

What this skill does


# Git Multi-Identity Configuration

Directory-scoped Git identity isolation: automatic email, GPG key, and SSH key selection based on repository location.

## Table of Contents

- [Overview](#overview)
- [When to Use This Skill](#when-to-use-this-skill)
- [Gather User Details First](#gather-user-details-first)
- [Quick Start](#quick-start)
- [Setup](#setup)
- [Audit](#audit)
- [Troubleshoot](#troubleshoot)
- [Architecture](#architecture)
- [Related Skills](#related-skills)
- [Version History](#version-history)

## Overview

Multi-identity isolation solves the problem of using different Git identities (email, GPG key, SSH key) across different contexts on the same machine. Instead of manually switching configuration or setting per-repo overrides, `includeIf` conditional includes automatically apply the correct identity based on which directory a repository lives in.

**What this provides:**

- Automatic `user.email` and `user.name` per directory tree
- Automatic GPG signing key selection per identity
- Automatic SSH key routing per identity (multiple GitHub accounts)
- Zero manual switching -- commit in any repo and the correct identity applies

## When to Use This Skill

- Setting up work vs personal Git identities on the same machine
- Configuring multiple GitHub/GitLab accounts with different SSH keys
- Fixing "Unverified" commits caused by email/GPG key mismatch
- Auditing that identity isolation is working correctly across directories
- Troubleshooting `includeIf` not matching, wrong GPG key used, or SSH "permission denied"
- Adding a new identity (new employer, new open-source persona)

## Gather User Details First

**Before executing any setup commands**, use `AskUserQuestion` to collect the user's specific details. Every identity setup is unique -- do not assume directory paths, email addresses, or identity names.

**Required information per identity:**

1. **Identity name** (e.g., "work", "personal", "freelance", "open-source")
2. **Directory path** where repos for this identity live (e.g., `~/Projects/work/`)
3. **Git email** for this identity
4. **Git name** (if different per identity, or one shared name)
5. **GPG signing?** Whether they want GPG signing (and whether keys already exist)
6. **SSH key routing?** Whether they need separate SSH keys per identity (e.g., multiple GitHub accounts)
7. **Platform** (Windows, macOS, Linux) -- determines `gitdir:` vs `gitdir/i:` syntax

**Example AskUserQuestion flow:**

- "How many Git identities do you need? What are their names (e.g., work, personal)?"
- "What directory contains your [identity] repositories?"
- "What email address should be used for [identity] commits?"
- "Do you already have GPG keys for each identity, or should we generate them?"
- "Do you use multiple GitHub/GitLab accounts (requiring separate SSH keys)?"

Only proceed with setup commands after collecting these details. Replace all placeholder values in the examples below with the user's actual values.

## Quick Start

Minimal end-to-end setup for two identities (work + personal):

```bash
# 1. Create directory-scoped gitconfig files
cat > ~/.gitconfig-work << 'EOF'
[user]
    email = [email protected]
    signingkey = <WORK_GPG_KEY_ID>
[core]
    sshCommand = ssh -i ~/.ssh/id_ed25519_work
EOF

cat > ~/.gitconfig-personal << 'EOF'
[user]
    email = [email protected]
    signingkey = <PERSONAL_GPG_KEY_ID>
[core]
    sshCommand = ssh -i ~/.ssh/id_ed25519_personal
EOF

# 2. Add includeIf directives to ~/.gitconfig
# (Windows: use gitdir/i: for case-insensitive matching)
git config --global --add includeIf."gitdir/i:C:/Projects/work/".path ~/.gitconfig-work
git config --global --add includeIf."gitdir/i:C:/Projects/personal/".path ~/.gitconfig-personal

# 3. Verify
cd ~/Projects/work/any-repo && git config user.email
# Expected: [email protected]

cd ~/Projects/personal/any-repo && git config user.email
# Expected: [email protected]
```

**For complete step-by-step setup**, see [references/identity-setup-guide.md](references/identity-setup-guide.md).

## Setup

### Directory Layout Convention

Organize repositories by identity under a common parent:

```text
~/Projects/
    work/           # All work repositories
        repo-a/
        repo-b/
    personal/       # All personal repositories
        my-project/
        dotfiles/
```

The parent directory (e.g., `work/`, `personal/`) is what `includeIf gitdir` matches against. Ask the user for their actual directory layout -- do not assume paths.

### Per-Identity Gitconfig Files

Create a separate gitconfig file for each identity. Each file overrides `user.email`, `user.name` (if different), `user.signingkey`, and optionally `core.sshCommand`.

**Work identity** (`~/.gitconfig-work`):

```ini
[user]
    email = [email protected]
    signingkey = ABC123DEF4567890
[core]
    sshCommand = ssh -i ~/.ssh/id_ed25519_work
```

**Personal identity** (`~/.gitconfig-personal`):

```ini
[user]
    email = [email protected]
    signingkey = 1234567890ABCDEF
[core]
    sshCommand = ssh -i ~/.ssh/id_ed25519_personal
```

### includeIf Directives

Add conditional includes to `~/.gitconfig`:

```ini
[user]
    name = Jane Developer
[commit]
    gpgsign = true

# Identity isolation
[includeIf "gitdir/i:C:/Projects/work/"]
    path = ~/.gitconfig-work
[includeIf "gitdir/i:C:/Projects/personal/"]
    path = ~/.gitconfig-personal
```

**Critical rules:**

- **Trailing slash required** -- `gitdir:C:/Projects/work/` not `gitdir:C:/Projects/work`
- **Windows: use `gitdir/i:`** -- case-insensitive matching (Windows paths are case-insensitive)
- **macOS/Linux: use `gitdir:`** -- case-sensitive matching is fine on case-sensitive filesystems
- The `user.name` in the main config acts as default; per-identity files only need to override what differs

### GPG Key Per Identity

Generate a separate GPG key for each identity email. See **git:gpg-signing** for detailed key generation.

```bash
# Generate work key (use work email)
gpg --full-generate-key
# Email: [email protected]

# Generate personal key (use personal email)
gpg --full-generate-key
# Email: [email protected]

# List keys to get IDs
gpg --list-secret-keys --keyid-format=long
```

Put the corresponding key ID in each identity's gitconfig file under `user.signingkey`.

### SSH Key Per Identity

Generate a separate SSH key for each identity:

```bash
# Work SSH key
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_work

# Personal SSH key
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_personal
```

**Two routing approaches** (pick one):

**Option A: `core.sshCommand` in per-identity gitconfig** (recommended -- simpler):

```ini
# In ~/.gitconfig-work
[core]
    sshCommand = ssh -i ~/.ssh/id_ed25519_work
```

**Option B: `~/.ssh/config` Host-based routing** (needed for multiple GitHub accounts):

```text
# ~/.ssh/config
Host github-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_work
    IdentitiesOnly yes

Host github-personal
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_personal
    IdentitiesOnly yes
```

With Host-based routing, use `url.insteadOf` in each identity config to transparently rewrite remote URLs:

```ini
# In ~/.gitconfig-work
[url "git@github-work:"]
    insteadOf = [email protected]:
```

See [references/identity-setup-guide.md](references/identity-setup-guide.md) for complete SSH routing details.

### Adding Keys to GitHub

Each identity's SSH and GPG public keys must be uploaded to the corresponding GitHub account:

1. **SSH key**: Settings > SSH and GPG keys > New SSH key
2. **GPG key**: Settings > SSH and GPG keys > New GPG key (`gpg --armor --export <KEY_ID>`)
3. **Verify email**: The email on the GPG key must be a verified email on the GitHub account

## Audit

Verify identity isolation is working correctly across all directories.

### Check Effective Identity

```bash
# Check effective identity in any directory
cd /path/to/repo
git config 

Related in Productivity