Patrick Steinhardt <ps@xxxxxx> writes: > On Thu, Aug 21, 2025 at 09:05:30AM -0700, Junio C Hamano wrote: >> Patrick Steinhardt <ps@xxxxxx> writes: >> >> > You're on a case-insensitive filesystem, and the remote you are >> > trying to fetch from has references that only differ in casing. It >> > is impossible to store such references with the "files" backend. You >> >> "backend." -> "backend on your system." >> >> > can either accept this as-is, in which case you won't be able to >> > store all remote references on disk. Or you can alternatively >> >> I do not see the former as a viable choice, though. When this >> happens, the clone or fetch fails and the user cannot catch up to >> the upstream development, no? You have to futz with the fetch >> refspec to cause refs your filesystem cannot store ignored in order >> to make progress on other refs, but that is making the user do more >> than accepting this as-is. > > Oh, yes, right now it's too involved. What I'm proposing is to mark the > transaction as allowed-to-fail, and in that case we'd be able to fetch > and store refs in this case again. The result would still be broken, but > it would be broken in a similar way as before. There's one difference > though: we'd accept the _first_ conflicting ref now, whereas before we > accepted the _last_ conflicting ref. I replied to one of the earlier emails, but ended up only sending it to Peff by mistake. Re-sending parts of it now. The fix itself isn't too involved: diff --git a/refs/files-backend.c b/refs/files-backend.c index 088b52c740..5c31b02e6b 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -776,6 +776,8 @@ static enum ref_transaction_error lock_raw_ref(struct files_ref_store *refs, goto retry; } else { unable_to_lock_message(ref_file.buf, myerr, err); + if (myerr == EEXIST) + ret = REF_TRANSACTION_ERROR_NAME_CONFLICT; goto error_return; } } and this would fix the issue, when tested on a case-insensitive filesystem: $ ~/code/git/build/bin-wrappers/git fetch -f origin 'refs/heads/*:refs/heads/*' remote: Enumerating objects: 15, done. remote: Counting objects: 100% (15/15), done. remote: Compressing objects: 100% (9/9), done. remote: Total 15 (delta 3), reused 0 (delta 0), pack-reused 0 (from 0) Unpacking objects: 100% (15/15), 3.54 KiB | 3.54 MiB/s, done. From https://gitlab.com/knayakgl/case-insensitive-refs * [new branch] SampLe -> SampLe * [new branch] Sample -> Sample * [new branch] main -> main * [new branch] sample -> sample * [new branch] SampLe -> origin/SampLe * [new branch] Sample -> origin/Sample * [new branch] main -> origin/main * [new branch] sample -> origin/sample error: some local refs could not be updated; try running 'git remote prune origin' to remove any old, conflicting branches error: fetching ref refs/heads/sample failed: refname conflict error: fetching ref refs/remotes/origin/Sample failed: refname conflict error: fetching ref refs/remotes/origin/sample failed: refname conflict $ git for-each-ref 24abc5ed19b517692bb4245eb4185dd5a86d7376 commit refs/heads/SampLe 24abc5ed19b517692bb4245eb4185dd5a86d7376 commit refs/heads/main 24abc5ed19b517692bb4245eb4185dd5a86d7376 commit refs/remotes/origin/SampLe 24abc5ed19b517692bb4245eb4185dd5a86d7376 commit refs/remotes/origin/main But like you noted, we end up saving the first reference rather than the last. Either isn't ideal, so while there is a change in behavior, this is better than the complete failure of the command. > In any case, I very much feel like we should know to warn about this > case and guide readers towards a proper solution. > > Patrick
Attachment:
signature.asc
Description: PGP signature