Documentation

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.

Compatability

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 and Run

Build locally:

cargo build --release

Run the binary:

./target/release/gitprofiles --help

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

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.

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.

Nuance

There is one behavior that can look confusing if it happens to you... During init, gitprofiles sets user.useConfigOnly=true globally. This is so that Git doesn't aut-guesses identity from the system username/hostname. That means in a repository where you have not set a local profile yet, and if global user.name/user.email are unset, a commit may fail with Git's own message:

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

This is expected, and it is still policy enforcement doing its job.

The "fix" is to run gitprofiles set-profile <name> in that repository, then gitprofiles check, and try again. After local profile setup is valid, commits/pushes will work. And you do not need global user.name/user.email, it's optional.

Limitations

  1. There is no client-side hook for local git tag creation. So tag creation itself is not blocked. The main identity risk is with annotated tags, because they embed tagger identity metadata, and that can be published when tags are pushed.

  2. gitprofiles 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. gitprofiles init 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/user.email mismatch

Repository identity has drifted from the selected profile. Re-apply with gitprofiles set-profile <name>, then confirm with gitprofiles check.

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.