#git #profile #cli #credentials

bin+lib gitprofiles

A CLI for managing multiple Git identities with local enforcement

4 releases (2 breaking)

Uses new Rust 2024

new 0.2.0 Feb 22, 2026
0.1.1 Feb 22, 2026
0.1.0 Feb 21, 2026
0.0.1 Feb 6, 2026

#458 in Development tools

MIT license

47KB
1K SLoC

gitprofiles

gitprofiles is CLI for managing multiple Git identities with local enforcement.

The intended workflow is:

  • first, define profiles once
  • then, set one profile per repository

Commits/pushes are blocked when profile state is missing or mismatched, although, there are some limitations. Please read below.

Compatibility

The only supported platforms are:

  • Linux/POSIX shell environments

The program may or may not work on other platforms. Support for them is not planned either.

Install

You must have cargo installed on your system.

cargo install gitprofiles

Quickstart

  1. Initialize global integration:
gitprofiles init
  1. Create a profile (interactive):
gitprofiles create
  1. In each repository, select a profile:
gitprofiles set-profile work
  1. Validate repository state:
gitprofiles check

PROTIP: gitp is an alias for invoking this program, instead of gitprofiles.

Commands

  • gitprofiles init
  • gitprofiles create
  • gitprofiles set-profile <name>
  • gitprofiles check
  • gitprofiles list
  • gitprofiles remove <name>

How Enforcement Works

The way gitprofiles was designed is straightforward. It does not try to wrap Git or replace its behavior, but instead, it adds a guardrail at the two moments where identity mistakes usually matter most. They're during, 1: creating commits, and, 2: pushing changes.

When you run gitprofiles init, the tool creates two hooks under ~/.config/gitprofiles/hooks: prepare-commit-msg and pre-push. Both hooks call gitprofiles check.

gitprofiles check is the policy gate. It reads your repo's local gitprofiles.profile, user.name, and user.email, then compares that state against the profile definition in ~/.config/gitprofiles/profiles.toml. If the profile marker is missing, if the profile name is not found in the TOML file, or if local name/email drift from that profile, the operation is rejected.

During pre-push, Git also sends the list of refs that are about to be pushed. gitprofiles check reads that payload and inspects pushed tags. If a pushed tag is an annotated tag object, gitprofiles validates its embedded tagger identity against your selected profile. If they do not match, the push is blocked.

So practically, once you run gitprofiles set-profile <name> in a repo, the checks keep that repo locked to the specified profile, unless you intentionally change something.

Limitations

  1. This program cannot block local annotated-tag creation (Git has no client hook for that), but it does block pushes that would publish annotated tags whose embedded tagger identity does not match the selected profile.

  2. This program is just a client-side enforcement, which is great enough. However, local hooks can be bypassed if things were invoked in ways that skip Git.

  3. The initialization command will refuse when core.hooksPath is already set globally, and it will also refuse if managed hook targets already exist. This is so the program does not overwrite an existing hook setup. A hook integration mode that can coexist with pre-existing hooks (chaining instead of refusing by default) is planned.

Troubleshooting

refusing to initialize: global core.hooksPath is already set

The program detected an existing hook setup and intentionally refused to overwrite it. That is currently a hard stop by design. You need to clear or migrate that existing hooks path manually before running gitprofiles init.

missing local key 'gitprofiles.profile'

That repository has not been assigned a profile marker yet. Run gitprofiles set-profile <name> in that repo.

profile '<name>' does not exist

The profile name is not in ~/.config/gitprofiles/profiles.toml. Run gitprofiles list to see existing names, or create the profile first via gitprofiles create.

local user.name mismatch (expected '...', found '...')

The repository's local user.name drifted from the selected profile. Re-apply with gitprofiles set-profile <name>, then confirm with gitprofiles check.

local user.email mismatch (expected '...', found '...')

The repository's local user.email drifted from the selected profile. Re-apply with gitprofiles set-profile <name>, then confirm with gitprofiles check.

annotated tag 'refs/tags/<tag>' tagger mismatch

The tag object was created with a different tagger identity than the currently selected profile. Recreate the tag under the correct profile identity, then push again.

fatal: no email was given and auto-detection is disabled

Git is telling you there is still no valid local identity in that repository while user.useConfigOnly=true is active. Set the repo profile and retry. During init, this program sets user.useConfigOnly=true globally so Git does not auto-guess identity. That means this error is expected in repositories where no local profile has been set yet.

Dependencies

~3–6MB
~105K SLoC