Manage multiple Git identities (name, email, signing key) with automatic configuration based on repository URL patterns. Designed to work seamlessly with VS Code Dev Containers and SSH agent forwarding.
When working with multiple Git identities (personal, work, client projects), you need:
- Different
user.nameanduser.emailper repository - SSH commit signing with different keys
- Everything to work inside devcontainers where your host SSH keys live
Git Personas solves this by letting you define personas once, then automatically configuring repositories based on URL patterns—including inside devcontainers where VS Code forwards your SSH agent.
- 🔄 URL pattern matching - automatically select persona based on remote URL
- 🪝 Git hooks - configure repos at clone time (config written to
.git/config) - 🔐 SSH commit signing - uses your SSH keys via agent forwarding
- Single config -
~/.git-personas.ymlas source of truth - 🐳 Dev Container ready - works via SSH agent socket forwarding
# Install globally (recommended)
uv tool install git+https://github.com/rosstaco/git-personas
# Or for development
git clone https://github.com/rosstaco/git-personas.git
cd git-personas
uv sync# 1. Initialize config and install Git hooks
git-personas init
# 2. Add a persona (interactive - generates SSH key if needed)
git-personas add
# 3. Apply to existing repositories
git-personas apply ~/repos
# 4. Validate your setup
git-personas validateGit Personas provides two approaches that work together:
When you clone a repo, a post-checkout hook:
- Reads the remote URL
- Matches it to a persona's URL patterns
- Writes identity config directly to
.git/config
Why this matters for devcontainers:
- Config is stored in
.git/config, which is inside the repo - When you open the repo in a devcontainer, the config comes with it
- VS Code automatically forwards your SSH agent socket
- Your private signing keys remain on your host—commits just work
The sync command generates:
~/.gitconfig.d/<persona>files with inlined public keysincludeIfrules usinghasconfig:remote.*.url
This is useful for repos cloned before hooks were installed.
Config file: ~/.git-personas.yml
settings:
gpg_format: ssh # Use SSH keys for signing
sign_commits: true # Enable commit signing by default
personas:
# Work GitHub org (more specific patterns first)
github-work:
name: "Your Name"
email: "you@company.com"
signing_key: "~/.ssh/id_ed25519_work"
patterns:
- "https://github.com/my-company/**"
- "git@github.com:my-company/**"
# Personal GitHub (catch-all, lowest priority)
github-personal:
name: "Your Name"
email: "personal@example.com"
signing_key: "~/.ssh/id_ed25519_personal"
patterns:
- "https://github.com/**"
- "git@github.com:**"
# Azure DevOps (no SSH signing support)
azdo-work:
name: "Your Name"
email: "you@company.com"
signing_key: "~/.ssh/id_ed25519_azdo"
sign_commits: false # AzDO doesn't support SSH signature verification
patterns:
- "https://dev.azure.com/myorg/**"
- "git@ssh.dev.azure.com:v3/myorg/**"Pattern rules:
- Use
**to match across path separators - More specific patterns should come before catch-all patterns
- Both HTTPS and SSH URL formats are supported
Create a new configuration file and install clone hooks.
git-personas init # Create ~/.git-personas.yml + install hooks
git-personas init --path ./config.yml # Custom path
git-personas init --force # Overwrite existing
git-personas init --no-hook # Skip hook installationOptions:
-p, --path PATH- Path for config file (default: ~/.git-personas.yml)-f, --force- Overwrite existing config file--no-hook- Skip installing the post-checkout hook
Generate gitconfig files from YAML configuration (for includeIf approach).
git-personas sync # Apply changes
git-personas sync --dry-run # Preview without changes
git-personas sync --yes # Skip confirmation promptsOptions:
-c, --config PATH- Path to config file-n, --dry-run- Show what would be done without making changes-y, --yes- Automatically confirm prompts
What it does:
- Detects and offers to remove conflicting global
user.name/user.emailsettings - Generates
~/.gitconfig.d/<persona>files with inlined public keys - Updates
~/.gitconfigwithincludeIfrules
Show all configured personas in a table.
git-personas listInteractively add a new persona.
git-personas addFeatures:
- Prompts for persona name, display name, email
- Supports GitHub, Azure DevOps, GitLab, Bitbucket patterns
- Guides you through SSH signing key setup
- Shows upload instructions for each Git service
Show details for a specific persona.
git-personas show github-personalRemove a persona from configuration.
git-personas delete old-persona
git-personas delete old-persona --force # Skip confirmationShow which persona would be used for the current repository.
git-personas which # Check current repo
git-personas which --url git@github.com:org/repo # Test a URLOutput:
- Current git config (with source: repo or global)
- Matched persona details
- Whether repo is configured
Configure the current repository based on its remote URL.
git-personas configure-repo # Configure current repo
git-personas configure-repo --repo /path/to/repo # Specific repoThis is what the hooks call automatically, but you can run it manually.
Apply persona config to all git repositories in a directory.
git-personas apply ~/repos # Configure all repos
git-personas apply ~/repos --dry-run # Preview what would happen
git-personas apply ~/repos --force # Re-configure even if already doneOptions:
-n, --dry-run- Show what would be configured without making changes-f, --force- Re-configure repos even if already configured-c, --config PATH- Path to config file
Install the post-checkout hook for automatic repo configuration.
git-personas install-hookThe hook is installed to ~/.git-templates/hooks/ and Git's init.templateDir is configured. New clones will automatically get the hook.
How it works:
post-checkouthook: Configures new clones automaticallypost-mergehook: Configures old repos on first pull
Remove the git-personas hooks.
git-personas uninstall-hookCheck configuration and SSH agent status.
git-personas validateChecks:
- Public key files exist and are readable
- Keys are loaded in SSH agent
- URL patterns are defined
Preview the generated gitconfig includeIf section.
git-personas previewgit-personas --version # Show version
git-personas --help # Show helpGit Personas is designed with devcontainers in mind. Here's how it works:
- Your SSH keys stay on your host machine - never copied into containers
- VS Code forwards your SSH agent socket - the
SSH_AUTH_SOCKenvironment variable points to a socket that communicates with your host's SSH agent - Git hooks write config to
.git/config- this travels with the repo into the container - Commits are signed via the forwarded agent - Git uses the socket to request signatures from your host's keys
On your host machine:
# Install git-personas and set up hooks
git-personas init
git-personas add # Add your personas
# Make sure your signing keys are in the SSH agent
ssh-add ~/.ssh/id_ed25519_work
ssh-add ~/.ssh/id_ed25519_personalThat's it! When you clone repos on your host, the hook configures .git/config. When you open in a devcontainer, the config is there and SSH agent forwarding handles signing.
Inside a devcontainer:
# Check agent forwarding is working
ssh-add -l
# Check which persona is configured
git-personas which
# Test commit signing
echo "test" >> test.txt && git commit -am "test signed commit"
git log --show-signature -1If you need the sync command's includeIf rules inside containers, mount the config directory:
{
"mounts": [
"source=${localEnv:HOME}/.gitconfig.d,target=/home/vscode/.gitconfig.d,type=bind,readonly"
]
}Patterns use glob syntax where ** matches across path separators.
| Pattern | Matches |
|---|---|
git@github.com:company/** |
GitHub org (SSH) |
https://github.com/company/** |
GitHub org (HTTPS) |
https://github.com/** |
Any GitHub URL (catch-all) |
git@ssh.dev.azure.com:v3/org/** |
Azure DevOps (SSH) |
https://dev.azure.com/org/** |
Azure DevOps (HTTPS) |
git@gitlab.com:group/** |
GitLab group (SSH) |
git@bitbucket.org:workspace/** |
Bitbucket workspace (SSH) |
Tips:
- Define specific patterns (org/company) before catch-all patterns
- Both HTTPS and SSH URLs are normalized for matching
- Use
git-personas which --url <url>to test pattern matching
# Inside the container, check if agent is available
echo $SSH_AUTH_SOCK
ssh-add -lIf no keys are listed, ensure:
- SSH agent is running on your host
- Keys are added:
ssh-add ~/.ssh/id_ed25519_work - VS Code's SSH agent forwarding is enabled (default)
# Check signing is configured
git config --local user.signingkey
git config --local commit.gpgsign
# Verify the key is in the agent
ssh-add -l# See which persona matches
git-personas which
# Check local config
git config --local user.email
# Re-run configuration
git-personas configure-repo# Check hooks are installed
ls ~/.git-templates/hooks/
git config --global init.templateDir
# Reinstall if needed
git-personas install-hook# Check for global user settings
git config --global user.email
# Run sync to fix (it will prompt to remove them)
git-personas syncMIT