git 2.56 credential-store parses one URL per line (port included), not the key=value block shape the man page shows for ~/.git-credentials; a block-format file yields a silent empty get and git dies at askpass.
2.4 KiB
name, description
| name | description |
|---|---|
| gitea-token-out-of-remote-url | Move a Gitea/HTTP git token out of remote.origin.url into a credential store file, and verify auth works with prompts disabled. |
Move a git token out of the remote URL
A remote URL like http://user:<token>@host:port/org/repo.git puts the credential in
.git/config (copied by every clone), prints it in git remote -v, and git-lfs echoes the
whole URL in its Locking support detected on remote warning on every push.
1. Capture the token from the existing remote (never paste it into a message)
url=$(git remote get-url origin)
user=$(printf '%s' "$url" | sed -E 's#^http://([^:]+):[^@]+@.*$#\1#')
tok=$(printf '%s' "$url" | sed -E 's#^http://[^:]+:([^@]+)@.*$#\1#')
2. Write the credential file (URL form, port included)
umask 077
printf 'http://%s:%s@HOST:PORT\n' "$user" "$tok" > ~/.config/secrets/gitea
Git 2.56 credential-store does NOT parse the protocol=/host=/password= block shape
that git credential fill accepts on stdin: a block-format file gives a SILENT empty get,
then git falls through to askpass (could not read Username). One URL per line, port included.
3. Point git at it, strip the URL, silence the LFS echo
git config --global credential.helper 'store --file ~/.config/secrets/gitea'
git remote set-url origin http://HOST:PORT/org/repo.git
git config lfs.http://HOST:PORT/org/repo.git/info/lfs.locksverify true
4. Verify with prompts disabled (a hang is a failed credential)
printf 'protocol=http\nhost=HOST:PORT\n\n' | git credential-store --file ~/.config/secrets/gitea get
GIT_TERMINAL_PROMPT=0 git ls-remote --heads origin main # read auth
GIT_TERMINAL_PROMPT=0 git push --dry-run origin main # write auth
git remote get-url origin # must contain no '@'
grep -l "$tok" ~/.gitconfig */.git/config ~/.zshrc # must find nothing
A successful push over the bare URL is the end-to-end proof: the credential came from the file.
5. Sweep the leak
Same shape on every clone on the host — loop over find ~ -maxdepth 4 -path '*/.git/config',
read remote.origin.url, scrub any URL containing @. One credential file serves them all
via the global helper.
Rotate
Rewrite only the credential file, then delete the old token in the Gitea UI (Settings → Applications). No remote URL, rc file, or repository changes.