Pick the right Git identity for each repository. A small, dependency-free CLI for Linux, macOS and Windows.
  • Rust 80.2%
  • Shell 9.3%
  • NSIS 7.9%
  • Makefile 2.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Dxsk ea49a021e6
All checks were successful
CI / check (push) Successful in 21s
docs: list the crates.io and AUR packages, sign release tags
2026-10-08 22:49:24 +02:00
.cargo feat: rewrite as a dependency-free Rust binary 2026-10-07 07:33:53 +02:00
.forgejo/workflows ci: replace an existing release when a tag is built again 2026-10-07 22:29:14 +02:00
.github/workflows ci: only mark the highest version as the latest GitHub release 2026-10-07 23:14:41 +02:00
installers build: group installers in an installers/ folder 2026-10-07 21:48:21 +02:00
packaging/aur fix(packaging): commit to the AUR with the project's git identity 2026-10-08 22:44:29 +02:00
src feat: show which config file edit opens 2026-10-07 22:06:46 +02:00
tests test: use a sed call that also works on macOS 2026-10-07 23:13:59 +02:00
.gitattributes build: use LF line endings everywhere 2026-10-07 22:16:49 +02:00
.gitignore feat: rewrite as a dependency-free Rust binary 2026-10-07 07:33:53 +02:00
Cargo.lock chore: release v1.2.1 2026-10-08 22:35:10 +02:00
Cargo.toml chore: release v1.2.1 2026-10-08 22:35:10 +02:00
CHANGELOG.md chore: release v1.2.1 2026-10-08 22:35:10 +02:00
identities.example.json feat: add CLI options, signing key support, auto-detection, and Makefile 2026-04-05 02:48:22 +02:00
LICENSE chore: initial commit 2026-03-16 00:15:07 +01:00
Makefile docs: list the crates.io and AUR packages, sign release tags 2026-10-08 22:49:24 +02:00
README.md docs: list the crates.io and AUR packages, sign release tags 2026-10-08 22:49:24 +02:00

git-identity

Pick the right Git identity for each repository, and stop committing with the wrong email.

Forgejo CI GitHub CI Release crates.io AUR Coverage Platforms License

Forgejo (main repository) · GitHub mirror


If you have a personal account, a work account and maybe a few open-source ones, sooner or later you push a commit signed with the wrong address. git-identity keeps your identities in one file and sets the right user.name, user.email and signing key on each repository, either from a quick fuzzy picker or automatically from the remote URL.

It is a single small binary. The only thing it needs at runtime is git.

$ git identity
? Select git identity (suggested: Work) ›
❯ Work | Jane Doe <jane@company.com>
  Personal | Jane Doe <jane@example.com>

Identity set for this repo:
  user.name       = Jane Doe
  user.email      = jane@company.com

Installation

Prebuilt binaries for every release are on the GitHub releases page, which has every platform. The Forgejo releases carry the Linux and Windows x86_64 builds.

Package managers
Where Package Command
crates.io git-identity-manager cargo install git-identity-manager
AUR (Arch, Manjaro, CachyOS...) git-identity-manager-bin (prebuilt) yay -S git-identity-manager-bin
AUR git-identity-manager (built from source) yay -S git-identity-manager

The package is called git-identity-manager because git-identity was already taken on crates.io and the AUR, but the command it installs is still git-identity. The AUR packages conflict with the unrelated AUR git-identity package, which installs a command with the same name.

Windows

Download and run git-identity-x86_64-setup.exe (or the aarch64 one on ARM devices).

The installer works per user, so it does not ask for admin rights. It adds the program to your PATH and shows up in Apps & features if you want to remove it later.

For a silent install, pass /S:

.\git-identity-x86_64-setup.exe /S

If you would rather not install anything, grab the portable .zip and put git-identity.exe somewhere on your PATH.

Linux and macOS
curl -fsSL https://raw.githubusercontent.com/Dxsk/git-identity-manager/main/installers/install.sh | sh

The script downloads the archive that matches your system, checks it against the release's SHA256SUMS, and puts the binary in ~/.local/bin. You can change that with PREFIX, and pin a release with VERSION:

curl -fsSL https://raw.githubusercontent.com/Dxsk/git-identity-manager/main/installers/install.sh | PREFIX=/usr/local VERSION=v1.1.0 sh
From source

You need a Rust toolchain.

make install                    # builds and installs to ~/.local/bin/git-identity
make install PREFIX=/usr/local  # or anywhere else
make uninstall

Cargo works too, from crates.io or straight from the repository:

cargo install git-identity-manager
cargo install --git https://github.com/Dxsk/git-identity-manager
Verifying a download

Every release ships two checksum files:

  • SHA256SUMS lists the archives and installers you download.
  • SHA256SUMS-binaries lists the git-identity binary inside each archive, as <target>/git-identity. Use it to check a binary you already extracted or installed.

On Linux and macOS:

sha256sum --ignore-missing -c SHA256SUMS   # macOS: shasum -a 256 --ignore-missing -c SHA256SUMS

On Windows:

(Get-FileHash .\git-identity-x86_64-setup.exe).Hash.ToLower()
(Get-FileHash "$env:LOCALAPPDATA\Programs\git-identity\git-identity.exe").Hash.ToLower()

Then compare the result with the matching line in the checksum file.

Getting started

Add your first identity. Run it inside a repository and it suggests your current name, email and a remote pattern based on origin:

git identity add

Or do it in one line, for scripts and dotfiles:

git identity add Work --name "Jane Doe" --email jane@company.com --remote 'github\.com[:/]my-company/'

From then on, run git identity inside any repository to choose who you are there. If you prefer editing the file by hand, git identity edit opens it in your editor.

Usage

The binary is called git-identity, so Git picks it up as a subcommand. git identity and git-identity do the same thing.

Command Shortcuts What it does
git identity Opens the fuzzy picker
git identity use <label> sw, switch Applies an identity by its label (case does not matter)
git identity auto Applies the identity whose remotes match origin
git identity list ls Lists your identities
git identity current cur, whoami Shows the identity set on this repository
git identity unset Removes it, so the global config applies again
git identity add [<label>] new, append Adds an identity (see below)
git identity remove [<label>] rm Removes an identity, or lets you pick one
git identity edit e Opens the config file in your editor
git identity hook Installs a reminder hook (see below)
git identity init Creates the config file from a template
git identity path Prints the config file location
git identity help h Shows the built-in help

The old --list, --current, --unset and --hook flags still work, so existing aliases and scripts keep running.

Options for add
Option
-n, --name <name> Value for user.name
-e, --email <email> Value for user.email
-k, --signing-key <key> Signing key
-r, --remote <regex> Remote pattern, can be given several times

Run add with no options and it walks you through every field. If you pass some options, it only asks for what is still missing. Outside a terminal it never asks, and fails if the label, name or email is missing.

add and remove rewrite the config file but keep any extra fields you added by hand.

Note

Use git identity help (or git-identity --help) to see the help. Git catches git identity --help before it reaches the tool and looks for a manual page instead, which does not exist.

Configuration

Config file format
{
  "identities": [
    {
      "label": "Work",
      "name": "Jane Doe",
      "email": "jane@company.com",
      "signingKey": "ssh-ed25519 AAAA...",
      "remotes": ["github\\.com[:/]my-company/"]
    },
    {
      "label": "Personal",
      "name": "Jane Doe",
      "email": "jane@example.com"
    }
  ]
}
Field Required Description
label ✓ The name you see in the picker and pass to use
name ✓ Value for user.name
email ✓ Value for user.email
signingKey GPG or SSH key used to sign commits. Setting it also turns on commit.gpgsign and picks gpg.format for you: ssh when the key starts with ssh- or key::, openpgp otherwise.
remotes Regular expressions checked against the origin URL. The first identity that matches is suggested in the picker and used by auto.
Editing the file

git identity edit opens the config in your system's default editor: the app tied to .json files on Windows, the default text editor on macOS, and whatever xdg-open picks on Linux. Those apps keep running in the background, so the tool waits for you to press Enter once you have saved.

If you set an editor for Git (GIT_EDITOR, core.editor, VISUAL or EDITOR), that one is used instead and the tool simply waits for it to close. This is also what happens over SSH or anywhere without a desktop session. For example, to use VS Code:

git config --global core.editor "code --wait"

Once you are done, the file is checked. If it is not valid you can reopen it to fix the mistake. If you give up, the previous config is restored and your edit is kept in identities.json.rejected, so nothing is lost and the tool keeps working.

If the file does not exist yet, it is created from the example template first.

Where the config lives

git-identity looks for the file in this order and uses the first one that applies:

  1. The path in GIT_IDENTITY_CONFIG
  2. $XDG_CONFIG_HOME/git-identity/identities.json, if XDG_CONFIG_HOME is set
  3. The default location for your system:
    • Windows: %APPDATA%\git-identity\identities.json
    • Linux and macOS: ~/.config/git-identity/identities.json
Picking the identity automatically

When an identity has remotes patterns and one of them matches the repository's origin URL, the picker opens with that identity already selected. You only have to press Enter.

To skip the picker altogether, for example in a script or a Git hook, use:

git identity auto

It fails with a clear message when no pattern matches, so it is safe to chain.

Reminder hook

Inside a repository, git identity hook adds a small post-checkout hook. After each checkout, it prints a reminder if no local identity is set yet.

The hook is a plain POSIX sh script. Git for Windows runs these out of the box, so it behaves the same on every platform. If you already have a post-checkout hook, the reminder is appended to it instead of replacing it.

Development

Building and testing
make build     # optimized binary in target/release/
make test      # unit and integration tests
make coverage  # tests plus line coverage (needs cargo-llvm-cov)
make lint      # rustfmt and clippy

The integration tests run the real binary against throwaway repositories, with your global Git config kept out of the way.

Line coverage is around 74%. The Forgejo CI measures it on every push and prints the per-file figures in the "Tests and coverage" step. What is left out is mostly the interactive part (the picker, the add wizard, opening the system editor), which needs a real terminal or desktop and is checked by hand. For a small CLI like this one, chasing 100% is not worth it.

To build the Windows installer yourself, install NSIS and run:

cargo build --release
makensis /DVERSION=1.1.0 installers\git-identity.nsi

The setup file ends up in dist\.

CI and releases

The project lives on Forgejo and is push-mirrored to GitHub. Each side has its own pipeline:

Forgejo (.forgejo/workflows/) GitHub mirror (.github/workflows/)
On every push Format, lint and tests on Linux Format and lint, tests on Linux, macOS and Windows
On a v* tag Linux x86_64 and aarch64, Windows x86_64 and its installer, all cross-compiled from one Linux runner The same, plus macOS (Intel and Apple Silicon) and Windows ARM

Both releases include SHA256SUMS and SHA256SUMS-binaries.

Cutting a release
  1. Describe the changes under ## Unreleased in CHANGELOG.md.

  2. Run the release target with the new version:

    make release V=1.1.0
    

    It sets the version in Cargo.toml and Cargo.lock, turns the Unreleased heading into 1.1.0 (date), then commits and creates the signed v1.1.0 tag (git tag -s, so a GPG signing key is needed). Nothing is pushed yet, so you can still check the result.

  3. Push to Forgejo:

    git push --follow-tags
    

The tag starts the Forgejo release, and the mirror carries it to GitHub, which starts the GitHub one. Both refuse to run if the tag does not match the version in Cargo.toml.

  1. Once the GitHub release has all its assets, publish the packages:

    cargo publish                                # crates.io
    sh packaging/aur/render.sh 1.1.0 --publish   # AUR, needs your AUR SSH key
    

    Without --publish, render.sh only writes the PKGBUILD and .SRCINFO files to dist/aur/ for review.

Since the mirror overwrites GitHub on every sync, never commit or tag directly on GitHub.

License

MIT