Repository navigation
SSH mirrors fail on gitcache -u because URL normalization drops the username #159
Description
Affected versions: v1.0.20 onwards (since commit 54147ff "feature: Normalize URLs to maximize cache usage.")
Description
Mirrors created from SSH URLs (both ssh://user@host/... and scp-style git@host:path) fail to
update via gitcache -u or once the update interval triggers a fetch.
Root cause
GitMirror._clone()storesself.normalized_urlin the database, andGitMirror.normalize_url()
discards theuser@part of the URL.git_update_all_mirrors()constructs eachGitMirrorfrom its path only, soself.urlis read
back from the database and no longer contains the username._add_credentials_to_remote()then comparesself.urlwithstrip_credentials(self.url); they
are equal, so the credentials are never restored on theoriginremote (the "Temporarily
restoring credentials..." message never appears). The fetch runs againsthost:pathwithout a
username and SSH authentication fails (it uses the local login name instead of e.g.git).
Mirrors created before v1.0.20 still have the full git@... URL in the database, so they
restore credentials and update fine. This makes the failure look inconsistent: mirrors of the same
host can pass or fail depending on when they were first cloned.
The bug is an interaction of two features: normalize_url() dropping user@ from the database URL
(commit 54147ff, v1.0.20) and the credential handling from #131 / #134 assuming the database URL is
a usable source of truth for restoring credentials. For SSH URLs it is not, because the username was
already lost during normalization.
A note on intent (please correct me if I read this wrongly)
I am guessing at the original intention here, so please treat the following as an inference rather
than a statement of fact:
- Dropping
user@innormalize_url()(54147ff) looks deliberate for cache deduplication, and at
the time it was harmless: before Feature: Handle credentials in URLs #134, the database URL was never used for fetching, as updates
used the mirror's ownremote.origin.urlwhich still contained the full clone URL. - The credential stripping from Support the use case of running in CI with temporary Git credentials #131 / Feature: Handle credentials in URLs #134 / Feature: Mask credentials #137 appears to be aimed at secrets in http(s) URLs
(GitLab CI tokens,user:token@); every example in the Support the use case of running in CI with temporary Git credentials #131 discussion is https, and SSH is not
mentioned. Sincestrip_credentials()applies the same regex to all URL shapes, it also removes
the bare username from scp-style URLs, where a password is not even syntactically possible. - The stated goal in Feature: Handle credentials in URLs #134 was that "fetch and pull actions still work" via temporary restoration.
For SSH URLs read from the database this no longer holds, which is why I suspect the SSH username
removal is unintended collateral rather than a design decision.
I am aware the SSH LFS tests added later (test_15_lfs.py, PR #139) assert the database URL without
git@, so if stripping the SSH username is intended behaviour, I would be happy to hear the
reasoning and what the recommended setup is (e.g. relying on ~/.ssh/config to supply the user).
Steps to reproduce
gitcache git clone git@<some-host>:<group>/<repo>.git(with gitcache >= 1.0.20)- Note that
~/.gitcache/dbstores"url": "<some-host>:<group>/<repo>"withoutgit@. gitcache -u- The update fails with an SSH authentication/permission error; the log shows no "Temporarily
restoring credentials on the mirror remote URLs." line.
Suggested fix
The username of an SSH URL is not a credential secret; it is required to authenticate. Suggested
changes:
normalize_url(): keepuser@forssh://and scp-style URLs (dropping only a password), so the
database retains a usable upstream URL. The mirror path can continue to ignore the username so
cache sharing still works.helpers.strip_credentials(): for SSH-style URLs, keep the username and strip/mask only the
password; keep current behaviour for http(s)/ftp(s).
Note: existing databases with already-stripped URLs cannot be repaired automatically since the
username is lost; affected users need to re-add the username to ~/.gitcache/db or re-create the
mirror.
I have a patch with unit tests ready and can open a PR if this approach is acceptable.
This issue was investigated and drafted with the assistance of Claude Code; the analysis of the
repository history and the proposed fix were reviewed by a human before posting.
Activity
seeraven commentedon Jul 18, 2026
Hi, thanks to bring that up. 👍 It looks indeed like a bug. I have to look a little bit deeper into the issue tomorrow or next week, as I'm currently busy. If you like, you could already start the PR.
bugfix: Keep the username of SSH-style URLs when normalizing and stri…
bugfix: Keep the username of SSH-style URLs when normalizing and stri…
waipeng commentedon Jul 21, 2026
Thanks for replying. I am fortunate enough to have access to Claude, and have used it to get something decent. I have 2 commits with different approaches, hope you can let me know what you prefer.
I understand some maintainers may not like AI generated code, so feel free to take parts of this or disregard, but I just wanted to contribute as this has helped me in my work.
Thanks for this wonderful software.
github-actions commentedon Aug 21, 2026
This issue is stale because it has been open for 30 days with no activity.
github-actions commentedon Sep 4, 2026
This issue was closed because it has been inactive for 14 days since being marked as stale.
seeraven commentedon Sep 6, 2026
Sorry for closing the issue. We have school holidays at the moment and it's hard to find time to work on this. ;-)
In general, I have no problem with AI generated code, but it usually requires a really thorough review. AI tends to create stuff that really looks good but might have subtle bugs hidden somewhere.
seeraven commentedon Sep 6, 2026
I like the first one better as it is easier to read. Can you open a pull request for it?
Bilb commentedon Sep 25, 2026
We hit the same root cause through a different path: the same repository reached through an HTTPS URL, here an HTTPS clone in a CI step on a machine whose own checkouts use ssh. The mirror update then has nothing to restore the user from and connects as
<local user>@github.com.I opened #163 with @waipeng's commit 50b2aac kept as is, author preserved, plus a repair for mirrors already stripped by v1.0.31 to v1.0.34, the test adjustments and a changelog entry. @waipeng, if you would rather open your own PR, say so and I will close mine.
test: Adjust the ssh tests to the database keeping the user of ssh URLs