git-credential-readonly is a read-only replacement for
git-credential-store. It handles the get action and intentionally ignores
store and erase, so Git can retrieve credentials without modifying the
credential files.
This is useful when personal and organization tokens for the same host live in
different files. Git sends approved credentials to every configured helper;
using store for both files can therefore copy an organization token into the
personal credential file.
For example:
[credential "https://github.com/org-name/"]
helper = readonly --file ~/.git-credentials-work
[credential]
helper = readonlyWith readonly, the organization token can be read from its dedicated file
without being written to the personal store at ~/.git-credentials.
go install github.com/ttys3/git-credential-readonly@latestThe helper supports these actions:
git-credential-readonly <get|store|erase>
For a single default credential file, configure it as follows:
git config --global credential.helper readonlyThe order of credential.helper entries is significant. Git tries helpers in
order until it has both a username and a password. An empty helper value has a
special meaning: it clears every helper collected before it.
This commonly affects users whose system Git configuration already selects a helper such as:
osxkeychainon macOS;managerormanager-corefrom Git Credential Manager;libsecreton Linux.
The following ordering is incorrect:
[credential "https://github.com/"]
helper = readonly --file ~/.git-credentials-work
[credential]
helper =
helper = readonlyThe empty value clears both the inherited system helper and the GitHub-specific
helper. Git then runs only git credential-readonly get, which reads the
default ~/.git-credentials file and may fall back to prompting for a username.
The required order is:
- reset inherited helpers;
- add host- or organization-specific helpers;
- add the general fallback helper last.
See the complete, sanitized examples/gitconfig file:
[credential]
helper =
[credential "https://github.com/"]
helper = readonly --file ~/.git-credentials-work
useHttpPath = true
[credential "https://git.example.com/"]
helper = readonly --file ~/.git-credentials-work
[credential "https://gitlab.example.com/"]
helper = readonly --file ~/.git-credentials-work
useHttpPath = true
[credential]
helper = readonlyCopy the relevant sections into ~/.gitconfig and replace the example host and
file names as needed.
Git removes the HTTP(S) path before invoking external helpers unless
credential.useHttpPath
is enabled. Git's built-in credential-store then compares a supplied path
exactly. This helper intentionally extends that behavior with slash-delimited
path scopes: group/subgroup matches both itself and descendants such as
group/subgroup/project.git, but it does not match group/subgroup-backup.
A trailing slash on a credential path is optional. Non-exact scope matches are
rejected when either path contains a . or .. segment, including a
percent-encoded form that remains after Git's URL decoding.
Credential lines are checked from top to bottom, like credential-store, and
the first match wins. Put full repository paths before subgroup paths, and put
subgroup paths before broader organization or account paths.
~/.git-credentials-work:
https://example-user:repository-token@github.com/example-org/private-repository.git
https://example-user:organization-token@github.com/example-org
https://example-user:subgroup-token@gitlab.example.com/group/subgroup
https://example-user:work-token@git.example.com
The default personal file may contain:
~/.git-credentials:
https://example-user:personal-token@github.com/example-user
Credential files use the official
git-credential-store storage format:
one credential URL per line, without comments or blank lines. They contain
plaintext secrets. Never commit them, percent-encode special characters in
usernames and tokens, and restrict their permissions:
chmod 600 ~/.git-credentials ~/.git-credentials-workTo see which helper Git actually executes without allowing an interactive prompt, run:
GIT_TRACE=1 GIT_TERMINAL_PROMPT=0 \
git ls-remote --symref origin HEADFor the example configuration, the trace should include:
git credential-readonly --file ~/.git-credentials-work get
If it includes only the following command, check the ordering of the empty helper and the URL pattern used by the scoped helper:
git credential-readonly get
You can inspect where generic and GitHub-specific settings came from with:
git config --show-origin --show-scope --get-all credential.helper
git config --show-origin --show-scope \
--get-all credential.https://github.com/.helper- Git credential storage
git credentialinput/output formatgit-credential-storestorage and lookup behaviorcredential.helperconfigurationcredential.useHttpPathconfiguration- Git credential-context matching
- Git's exact credential field matcher
- Git's
credential-storelookup loop - Git's credential URL parser
- Git's credential URL decoder