Files
small-scripts/specs/git-identity.spec.md
Paul O'Reilly f21506af19 Add git-identity: switch git author identity from a saved menu
Identities live in ~/.git-identities (alias|Name|email). Interactive
menu to select, add, or remove identities; direct mode via alias
argument; --global/-g scope flag (defaults to local inside a repo,
global fallback outside); --list/--current helpers. Full --dryrun
support and a 27-assertion test suite driven through dryrun.
GIT_IDENTITIES_FILE env override for testability.
2026-08-18 20:20:45 +12:00

4.1 KiB

git-identity

Purpose

Switch the git author identity (user.name + user.email) for the current repo or globally, from a menu of identities saved in ~/.git-identities.

Usage

git-identity [OPTIONS] [ALIAS]

Arguments

Argument Default Description
ALIAS Apply this saved identity directly (non-interactive). Omit for the interactive menu.

Flags

Flag Description
--help, -h Show usage information
--dryrun, -n Preview all actions without changing config or the identities file
--global, -g Apply to global git config instead of the current repo
--list, -l List saved identities and exit
--current, -c Show the identity in effect for the current directory and exit

Environment

Variable Description
GIT_IDENTITIES_FILE Override the identities file path (default ~/.git-identities). Used by tests.

Identities file format

One identity per line: alias|Name|email. Blank lines and lines starting with # are ignored.

# alias|Name|email
personal|Paul Example|paul@example.net
work|Paul Example|paul.example@corp.com

Behaviour

  1. Determine scope: --global → global config; otherwise local config if inside a git repository, else fall back to global (with a note).
  2. Direct mode (ALIAS given): look up the alias in the identities file; apply git config user.name + user.email in the chosen scope; print confirmation showing scope, name, and email.
  3. Interactive mode (no alias): print the identity currently in effect, then a numbered menu of saved identities plus a final option s) Something else....
    • Selecting a number applies that identity (as in direct mode).
    • s opens a submenu: a) Add identity, r) Remove identity, q) Cancel.
      • Add: prompts for alias, name, email; validates alias is unique and contains no |; validates email contains @; appends to the file; then offers to apply it now.
      • Remove: numbered menu of identities; selected line is deleted from the file. Never touches git config.
    • q or empty input cancels with exit 0.
  4. Applying an identity never modifies the identities file; add/remove never modify git config (except the post-add "apply now" offer).

Dryrun Behaviour

Every mutating action prints a [dryrun] line instead of acting:

  • Apply: [dryrun] Would set user.name 'NAME' and user.email 'EMAIL' (--local in /path/to/repo) (or (--global))
  • Add: [dryrun] Would append 'alias|NAME|EMAIL' to FILE
  • Remove: [dryrun] Would remove identity 'alias' from FILE

Menus and prompts still function in dryrun so a full flow can be rehearsed.

Edge Cases

Case Handling
Identities file missing (interactive) Offer to create it seeded with the current global identity, then continue to menu
Identities file missing (direct/--list) Error: "No identities file at FILE (run git-identity to create one)", exit 1
Unknown alias in direct mode Error: "No identity 'ALIAS' in FILE", exit 1; list available aliases
Empty identities file Menu shows only "Something else..."
Duplicate alias on add Error: "Alias 'X' already exists", re-prompt
Alias containing | Error: "Alias must not contain '|'", re-prompt
Not in a git repo, no --global Note "not inside a git repository — applying globally", apply to global
Malformed line in file Skipped silently (comment/blank handling covers this)

Examples

# Interactive menu
$ git-identity
Current identity (local): Paul Example <paul@example.net>

  1) personal    Paul Example <paul@example.net>
  2) work        Paul Example <paul.example@corp.com>
  s) Something else...

Select [1-2/s/q]: 2
Set user.name 'Paul Example' and user.email 'paul.example@corp.com' (--local in /home/paul/dev/myrepo)

# Direct, dryrun
$ git-identity -n work
[dryrun] Would set user.name 'Paul Example' and user.email 'paul.example@corp.com' (--local in /home/paul/dev/myrepo)

# List
$ git-identity --list
personal    Paul Example <paul@example.net>
work        Paul Example <paul.example@corp.com>