Credential managers and storage
Intermediate Git CLI
Why this matters
You paste a token once and never think about it again, which is exactly the problem on the day the token is wrong. Git keeps asking nothing and keeps failing, because something is answering on your behalf. Knowing where that something stores the answer turns a maddening loop into a one-line fix.
What a helper is
Which one you have:
$ git config --list --show-origin | grep credentialfile:/Applications/Xcode.app/Contents/Developer/usr/share/git-core/gitconfig credential.helper=osxkeychainOn this Mac the helper comes from Git's own system configuration, which is why nothing was set in ~/.gitconfig. If the command prints nothing, no helper is configured and you are asked every time.
| System | Usual helper | Where it stores |
|---|---|---|
| macOS | osxkeychain |
the login Keychain |
| Windows | manager (Git Credential Manager) |
Windows Credential Manager |
| Linux | libsecret |
the desktop keyring (GNOME Keyring, KWallet) |
| Anywhere | store |
a plain-text file, ~/.git-credentials |
| Anywhere | cache |
memory, for 15 minutes by default |
To set one:
$ git config --global credential.helper osxkeychain # macOS
$ git config --global credential.helper manager # Windows
$ git config --global credential.helper libsecret # LinuxRemoving a stored credential
This is the fix for the repeating error. Choose your platform:
macOS. Open Keychain Access, search for gitlab.com or github.com, and delete the "internet password" entry. Or from the terminal:
$ printf 'protocol=https\nhost=gitlab.com\n\n' | git credential-osxkeychain eraseWindows. Open Credential Manager (Control Panel → User Accounts → Credential Manager) → Windows Credentials, find git:https://gitlab.com, and remove it. Or:
$ printf 'protocol=https\nhost=gitlab.com\n\n' | git credential-manager eraseLinux with libsecret. Use Seahorse ("Passwords and Keys") and delete the entry for the host, or:
$ printf 'protocol=https\nhost=gitlab.com\n\n' | git credential-libsecret eraseremote: HTTP Basic: Access denied. The provided password or token is incorrect or your account has 2FA enabled and you must use a personal access token instead of a password.
fatal: Authentication failed for 'https://gitlab.com/northwind-trails/trailguide.git/'With store. Edit ~/.git-credentials and delete the line for that host.
The blank line at the end of each printf is required: it tells the helper the input is finished. After erasing, the next push asks for the username and token again.
The repeating-error pattern
If this appears again immediately after you created a fresh token, you almost certainly did not get the chance to type it: the helper answered first, with the old one. The sequence that always works:
- Create the new token and copy it.
- Erase the stored credential for that host, with the command for your system above.
- Push. Git asks for the username and password.
- Paste the new token.
How to do it
$ git config --list --show-origin | grep credential
$ printf 'protocol=https\nhost=gitlab.com\n\n' | git credential-osxkeychain erase
$ git pushReplace the helper name with yours. There is no "list all stored credentials" command; use the operating system's own tool for that.
VS Code uses the same helper, so an entry erased in the terminal is gone for VS Code too.
For its own GitHub sign-in, the Accounts icon at the bottom of the Activity Bar → your account → Sign Out clears VS Code's stored OAuth credential, which is separate from the Git helper's token.
Settings → Version Control → Git → Use credential helper decides whether IntelliJ delegates to the system helper. IntelliJ's own accounts live in Settings → Version Control → GitHub / GitLab, and its passwords in Settings → Appearance & Behavior → System Settings → Passwords.
If a stale credential persists, check both places: the system helper and IntelliJ's password safe.
Nothing is stored on the server side; the token page simply lists which tokens exist. If you suspect a token is being used from a machine you no longer control, the last-used date on that page tells you, and revoking is immediate.
Same: Settings → Developer settings → Personal access tokens shows the last-used date of each token, and Settings → Sessions and Settings → Applications show browser sessions and authorized apps, which is where a VS Code or IntelliJ sign-in appears.
Common mistakes
- Making new tokens without erasing the old credential. The classic loop. Erase first.
- Assuming there is one credential. The helper, VS Code's account and IntelliJ's safe are three separate stores.
- Using
storeon a work machine. A plain-text token file; use the keychain. - Forgetting the blank line in the
erasecommand, which then waits for more input; press Ctrl+D and try again with the newline. - Erasing the credential for the wrong host.
gitlab.comandgitlab.company.comare different entries.
Try it yourself
Goal: find out what is storing your credential, without breaking anything.
- Run
git config --list --show-origin | grep credentialand note the helper and the file it came from. - Open your operating system's credential tool (Keychain Access, Credential Manager, Seahorse) and search for
gitlab.comorgithub.com. - Look at the entry: note that the stored "password" is your token.
- Do not delete it unless it is broken; close the tool.
Expected result: one helper name, and one entry per host you have pushed to.
Show solution
If step 1 prints nothing and you are still not asked for a token on every push, an IDE is supplying it instead. If you are asked every time, no helper is configured; set one with the command for your system, and the next paste will be the last.