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]
helper = readonlyCopy the relevant sections into ~/.gitconfig and replace the example host and
file names as needed.
When useHttpPath = true, include a GitHub account or organization path in
each credential URL. An owner-only entry matches every repository belonging to
that owner, while a full repository path matches only that repository.
~/.git-credentials-work:
https://example-user:organization-token@github.com/example-org
https://example-user:repository-token@github.com/example-org/private-repository.git
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 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