* "lock file exists" when fetching in bare clone of repository
@ 2025-08-20 20:54 Joe Drew
2025-08-20 21:33 ` Jeff King
0 siblings, 1 reply; 16+ messages in thread
From: Joe Drew @ 2025-08-20 20:54 UTC (permalink / raw)
To: git@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 3613 bytes --]
Hi there!
I've got what I think is a bug in recent versions of git, at least as packaged for macOS by homebrew.
I'm cloning a fresh copy of a repository into a bare directory:
$ mkdir tmp
$ cd tmp
$ git init --bare
$ git remote add origin -- <VALID-URL>.git
$ git fetch -f origin 'refs/heads/*:refs/heads/*' 'refs/tags/*:refs/tags/*'
I'm doing this in a sort of roundabout way because this is exactly what `go mod download` does.
The fetch fails, returning status 255, with the below error message:
remote: Enumerating objects: 18733, done.
remote: Counting objects: 100% (562/562), done.
remote: Compressing objects: 100% (448/448), done.
remote: Total 18733 (delta 399), reused 144 (delta 112), pack-reused 18171
Receiving objects: 100% (18733/18733), 25.32 MiB | 7.93 MiB/s, done.
Resolving deltas: 100% (14608/14608), done.
From <VALID-URL>
[.... quite a number of branches and tags .....]
error: cannot lock ref 'refs/heads/ptv-2164': Unable to create '/Users/joe.drew/tmp/./refs/heads/ptv-2164.lock': File exists.
Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes
are terminated then try again. If it still fails, a git process
may have crashed in this repository earlier:
remove the file manually to continue.
This file doesn't exist; in fact, no such files exist:
$ ls refs/heads
$
However, the branch _does_ exist on the remote.
This error _does not_ happen in the Apple-supplied version of git: `git version 2.39.5 (Apple Git-154)`, but does in 2.51.0, which I installed with homebrew. (If this is a packaging error, I'll happily report to homebrew.)
I'd be more than happy to continue debugging this, though I can't share the repository as it's proprietary. I've also attached the git diagnostics, but they're not particularly helpful, I don't think.
[System Info]
git version:
git version 2.51.0
cpu: arm64
no commit associated with this build
sizeof-long: 8
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon
libcurl: 8.7.1
zlib: 1.2.12
SHA-1: SHA1_DC
SHA-256: SHA256_BLK
default-ref-format: files
default-hash: sha1
uname: Darwin 24.6.0 Darwin Kernel Version 24.6.0: Mon Jul 14 11:30:40 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T6041 arm64
compiler info: clang: 17.0.0 (clang-1700.0.13.3)
libc info: no libc information available
$SHELL (typically, interactive shell): /opt/homebrew/bin/bash
[Enabled Hooks]
CONFIDENTIALITY NOTICE AND DISCLAIMER : This telecommunication, including any and all attachments, contains confidential information intended only for the person(s) to whom it is addressed. Any dissemination, distribution, copying or disclosure is strictly prohibited and is not a waiver of confidentiality. If you have received this telecommunication in error, please notify the sender immediately by return electronic mail and delete the message from your inbox and deleted items folders. This telecommunication does not constitute an express or implied agreement to conduct transactions by electronic means, nor does it constitute a contract offer, a contract amendment or an acceptance of a contract offer. Contract terms contained in this telecommunication are subject to legal review and the completion of formal documentation and are not binding until same is confirmed in writing and has been signed by an authorized signatory.
[-- Attachment #2: git-diagnostics-2025-08-20-1637.zip --]
[-- Type: application/zip, Size: 790 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-20 20:54 "lock file exists" when fetching in bare clone of repository Joe Drew
@ 2025-08-20 21:33 ` Jeff King
2025-08-21 7:15 ` Patrick Steinhardt
` (2 more replies)
0 siblings, 3 replies; 16+ messages in thread
From: Jeff King @ 2025-08-20 21:33 UTC (permalink / raw)
To: Joe Drew; +Cc: git@vger.kernel.org
On Wed, Aug 20, 2025 at 08:54:37PM +0000, Joe Drew wrote:
> The fetch fails, returning status 255, with the below error message:
>
> remote: Enumerating objects: 18733, done.
> remote: Counting objects: 100% (562/562), done.
> remote: Compressing objects: 100% (448/448), done.
> remote: Total 18733 (delta 399), reused 144 (delta 112), pack-reused 18171
> Receiving objects: 100% (18733/18733), 25.32 MiB | 7.93 MiB/s, done.
> Resolving deltas: 100% (14608/14608), done.
> From <VALID-URL>
>
> [.... quite a number of branches and tags .....]
>
> error: cannot lock ref 'refs/heads/ptv-2164': Unable to create '/Users/joe.drew/tmp/./refs/heads/ptv-2164.lock': File exists.
>
> Another git process seems to be running in this repository, e.g.
> an editor opened by 'git commit'. Please make sure all processes
> are terminated then try again. If it still fails, a git process
> may have crashed in this repository earlier:
> remove the file manually to continue.
>
> This file doesn't exist; in fact, no such files exist:
>
> $ ls refs/heads
> $
>
> However, the branch _does_ exist on the remote.
This is a wild guess, but: are there any case collisions with that
branch name (e.g., PTV-2164 or something) in the upstream repo?
If so, and assuming you're on a case-insensitive filesystem, then the
lock files would collide. You wouldn't see anything after the fact
because git-fetch itself would create the colliding lockfile, and then
clean it up after hitting the fatal error.
If that is the case, you can try using the reftables backend in v2.51.0.
It doesn't use the filesystem for its ref storage or locking. Something
like:
git init --bare --ref-format=reftable
> This error _does not_ happen in the Apple-supplied version of git:
> `git version 2.39.5 (Apple Git-154)`, but does in 2.51.0, which I
> installed with homebrew. (If this is a packaging error, I'll happily
> report to homebrew.)
That is definitely weird, and not something I'd expect if it's just a
case collision. Is it possible for you to build Git from source? If so,
and the problem happens with your build of 2.51.0 but not v2.39.5, it
would be very enlightening to see the results of "git bisect". We can
provide more guidance if you need with that process.
-Peff
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-20 21:33 ` Jeff King
@ 2025-08-21 7:15 ` Patrick Steinhardt
2025-08-21 7:27 ` Jeff King
2025-08-22 13:28 ` Joe Drew
2025-08-26 11:19 ` Jeff King
2 siblings, 1 reply; 16+ messages in thread
From: Patrick Steinhardt @ 2025-08-21 7:15 UTC (permalink / raw)
To: Jeff King; +Cc: Joe Drew, git@vger.kernel.org, Karthik Nayak
On Wed, Aug 20, 2025 at 05:33:23PM -0400, Jeff King wrote:
> On Wed, Aug 20, 2025 at 08:54:37PM +0000, Joe Drew wrote:
>
> > The fetch fails, returning status 255, with the below error message:
> >
> > remote: Enumerating objects: 18733, done.
> > remote: Counting objects: 100% (562/562), done.
> > remote: Compressing objects: 100% (448/448), done.
> > remote: Total 18733 (delta 399), reused 144 (delta 112), pack-reused 18171
> > Receiving objects: 100% (18733/18733), 25.32 MiB | 7.93 MiB/s, done.
> > Resolving deltas: 100% (14608/14608), done.
> > From <VALID-URL>
> >
> > [.... quite a number of branches and tags .....]
> >
> > error: cannot lock ref 'refs/heads/ptv-2164': Unable to create '/Users/joe.drew/tmp/./refs/heads/ptv-2164.lock': File exists.
>
> >
> > Another git process seems to be running in this repository, e.g.
> > an editor opened by 'git commit'. Please make sure all processes
> > are terminated then try again. If it still fails, a git process
> > may have crashed in this repository earlier:
> > remove the file manually to continue.
> >
> > This file doesn't exist; in fact, no such files exist:
> >
> > $ ls refs/heads
> > $
> >
> > However, the branch _does_ exist on the remote.
>
> This is a wild guess, but: are there any case collisions with that
> branch name (e.g., PTV-2164 or something) in the upstream repo?
>
> If so, and assuming you're on a case-insensitive filesystem, then the
> lock files would collide. You wouldn't see anything after the fact
> because git-fetch itself would create the colliding lockfile, and then
> clean it up after hitting the fatal error.
That's a likely failure mode indeed.
> If that is the case, you can try using the reftables backend in v2.51.0.
> It doesn't use the filesystem for its ref storage or locking. Something
> like:
>
> git init --bare --ref-format=reftable
Note that you can also `git clone --ref-format=reftable` directly, so
there's no need to go via git-init(1) first.
> > This error _does not_ happen in the Apple-supplied version of git:
> > `git version 2.39.5 (Apple Git-154)`, but does in 2.51.0, which I
> > installed with homebrew. (If this is a packaging error, I'll happily
> > report to homebrew.)
>
> That is definitely weird, and not something I'd expect if it's just a
> case collision. Is it possible for you to build Git from source? If so,
> and the problem happens with your build of 2.51.0 but not v2.39.5, it
> would be very enlightening to see the results of "git bisect". We can
> provide more guidance if you need with that process.
Curious indeed. Another relevant part could be the new batched mode that
we have recently introduced in git-fetch(1). Previously we would've
updated refs one by one, and potentially that led to us writing the same
ref multiple times due to case-insensitivity? The result would be quite
broken in that case, but at least the fetch would've finished. Does make
me wonder though what subsequent fetches did, and whether we always tend
to flip-flop the value of such a ref.
But with batched transactions that's not possible anymore, as we would
indeed try to lock the same ref twice. Assuming that this really is the
case, I wonder whether we should detect this case, tell the user that
it's impossible to store all refs on their system, and then continue
regardless while ejecting that specific ref from the transaction.
Patrick
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-21 7:15 ` Patrick Steinhardt
@ 2025-08-21 7:27 ` Jeff King
2025-08-21 10:09 ` Patrick Steinhardt
2025-08-21 15:47 ` Junio C Hamano
0 siblings, 2 replies; 16+ messages in thread
From: Jeff King @ 2025-08-21 7:27 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: Joe Drew, git@vger.kernel.org, Karthik Nayak
On Thu, Aug 21, 2025 at 09:15:47AM +0200, Patrick Steinhardt wrote:
> > > This error _does not_ happen in the Apple-supplied version of git:
> > > `git version 2.39.5 (Apple Git-154)`, but does in 2.51.0, which I
> > > installed with homebrew. (If this is a packaging error, I'll happily
> > > report to homebrew.)
> >
> > That is definitely weird, and not something I'd expect if it's just a
> > case collision. Is it possible for you to build Git from source? If so,
> > and the problem happens with your build of 2.51.0 but not v2.39.5, it
> > would be very enlightening to see the results of "git bisect". We can
> > provide more guidance if you need with that process.
>
> Curious indeed. Another relevant part could be the new batched mode that
> we have recently introduced in git-fetch(1). Previously we would've
> updated refs one by one, and potentially that led to us writing the same
> ref multiple times due to case-insensitivity? The result would be quite
> broken in that case, but at least the fetch would've finished. Does make
> me wonder though what subsequent fetches did, and whether we always tend
> to flip-flop the value of such a ref.
Ah, good catch. That would explain the behavior change perfectly. My money is
on a case collision, then. :)
> But with batched transactions that's not possible anymore, as we would
> indeed try to lock the same ref twice. Assuming that this really is the
> case, I wonder whether we should detect this case, tell the user that
> it's impossible to store all refs on their system, and then continue
> regardless while ejecting that specific ref from the transaction.
Maybe it is too optimistic to think that they will just start using
reftable in Git 3.0, and we can avoid extra code to detect this?
-Peff
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-21 7:27 ` Jeff King
@ 2025-08-21 10:09 ` Patrick Steinhardt
2025-08-21 16:05 ` Junio C Hamano
2025-08-21 15:47 ` Junio C Hamano
1 sibling, 1 reply; 16+ messages in thread
From: Patrick Steinhardt @ 2025-08-21 10:09 UTC (permalink / raw)
To: Jeff King; +Cc: Joe Drew, git@vger.kernel.org, Karthik Nayak
On Thu, Aug 21, 2025 at 03:27:06AM -0400, Jeff King wrote:
> On Thu, Aug 21, 2025 at 09:15:47AM +0200, Patrick Steinhardt wrote:
>
> > > > This error _does not_ happen in the Apple-supplied version of git:
> > > > `git version 2.39.5 (Apple Git-154)`, but does in 2.51.0, which I
> > > > installed with homebrew. (If this is a packaging error, I'll happily
> > > > report to homebrew.)
> > >
> > > That is definitely weird, and not something I'd expect if it's just a
> > > case collision. Is it possible for you to build Git from source? If so,
> > > and the problem happens with your build of 2.51.0 but not v2.39.5, it
> > > would be very enlightening to see the results of "git bisect". We can
> > > provide more guidance if you need with that process.
> >
> > Curious indeed. Another relevant part could be the new batched mode that
> > we have recently introduced in git-fetch(1). Previously we would've
> > updated refs one by one, and potentially that led to us writing the same
> > ref multiple times due to case-insensitivity? The result would be quite
> > broken in that case, but at least the fetch would've finished. Does make
> > me wonder though what subsequent fetches did, and whether we always tend
> > to flip-flop the value of such a ref.
>
> Ah, good catch. That would explain the behavior change perfectly. My money is
> on a case collision, then. :)
>
> > But with batched transactions that's not possible anymore, as we would
> > indeed try to lock the same ref twice. Assuming that this really is the
> > case, I wonder whether we should detect this case, tell the user that
> > it's impossible to store all refs on their system, and then continue
> > regardless while ejecting that specific ref from the transaction.
>
> Maybe it is too optimistic to think that they will just start using
> reftable in Git 3.0, and we can avoid extra code to detect this?
Probably, yeah. I also think it shouldn't be too involved to have the
logic in Git. We can mark transactions as allowing for failures now, so
in the best case we'd just do that and then check whether we have any
errors.
We could also think about generating a hint that tells the user exactly
what's going on. E.g. something like this:
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
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
migrate your repository to use the "reftable" backend with the
following command:
git refs migrate --ref-format=reftable
Please keep in mind that not all implementations of Git support this
new format yet. So if you use tools other than Git to access this
repository it may not be an option to migrate to reftables.
The last part is what I'm working on right now. libgit2 is fully
functional now, but what is still lacking is reviews.
Patrick
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-21 7:27 ` Jeff King
2025-08-21 10:09 ` Patrick Steinhardt
@ 2025-08-21 15:47 ` Junio C Hamano
1 sibling, 0 replies; 16+ messages in thread
From: Junio C Hamano @ 2025-08-21 15:47 UTC (permalink / raw)
To: Jeff King
Cc: Patrick Steinhardt, Joe Drew, git@vger.kernel.org, Karthik Nayak
Jeff King <peff@peff.net> writes:
>> But with batched transactions that's not possible anymore, as we would
>> indeed try to lock the same ref twice. Assuming that this really is the
>> case, I wonder whether we should detect this case, tell the user that
>> it's impossible to store all refs on their system, and then continue
>> regardless while ejecting that specific ref from the transaction.
>
> Maybe it is too optimistic to think that they will just start using
> reftable in Git 3.0, and we can avoid extra code to detect this?
Or we can just tell them to use reftable way before Git 3.0; it is
not like we feel that the reftable is way too unstable that we won't
tag Git 3.0 until it gets ready---it is ready now.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-21 10:09 ` Patrick Steinhardt
@ 2025-08-21 16:05 ` Junio C Hamano
2025-08-22 6:13 ` Patrick Steinhardt
0 siblings, 1 reply; 16+ messages in thread
From: Junio C Hamano @ 2025-08-21 16:05 UTC (permalink / raw)
To: Patrick Steinhardt
Cc: Jeff King, Joe Drew, git@vger.kernel.org, Karthik Nayak
Patrick Steinhardt <ps@pks.im> 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.
> migrate your repository to use the "reftable" backend with the
> following command:
>
> git refs migrate --ref-format=reftable
>
> Please keep in mind that not all implementations of Git support this
> new format yet. So if you use tools other than Git to access this
> repository it may not be an option to migrate to reftables.
>
> The last part is what I'm working on right now. libgit2 is fully
> functional now, but what is still lacking is reviews.
>
> Patrick
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-21 16:05 ` Junio C Hamano
@ 2025-08-22 6:13 ` Patrick Steinhardt
2025-08-22 8:01 ` Karthik Nayak
0 siblings, 1 reply; 16+ messages in thread
From: Patrick Steinhardt @ 2025-08-22 6:13 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, Joe Drew, git@vger.kernel.org, Karthik Nayak
On Thu, Aug 21, 2025 at 09:05:30AM -0700, Junio C Hamano wrote:
> Patrick Steinhardt <ps@pks.im> 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.
In any case, I very much feel like we should know to warn about this
case and guide readers towards a proper solution.
Patrick
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-22 6:13 ` Patrick Steinhardt
@ 2025-08-22 8:01 ` Karthik Nayak
2025-08-22 17:47 ` Junio C Hamano
0 siblings, 1 reply; 16+ messages in thread
From: Karthik Nayak @ 2025-08-22 8:01 UTC (permalink / raw)
To: Patrick Steinhardt, Junio C Hamano
Cc: Jeff King, Joe Drew, git@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 3829 bytes --]
Patrick Steinhardt <ps@pks.im> writes:
> On Thu, Aug 21, 2025 at 09:05:30AM -0700, Junio C Hamano wrote:
>> Patrick Steinhardt <ps@pks.im> 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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 690 bytes --]
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-20 21:33 ` Jeff King
2025-08-21 7:15 ` Patrick Steinhardt
@ 2025-08-22 13:28 ` Joe Drew
2025-08-26 11:19 ` Jeff King
2 siblings, 0 replies; 16+ messages in thread
From: Joe Drew @ 2025-08-22 13:28 UTC (permalink / raw)
To: Jeff King; +Cc: git@vger.kernel.org
> This is a wild guess, but: are there any case collisions with that
> branch name (e.g., PTV-2164 or something) in the upstream repo?
Yes, actually! The only difference is in case (ptv-2164 vs PTV-2164).
> If that is the case, you can try using the reftables backend in v2.51.0.
> It doesn't use the filesystem for its ref storage or locking. Something
> like:
>
> git init --bare --ref-format=reftable
Reftable does, in fact, solve this!
>> This error _does not_ happen in the Apple-supplied version of git:
>> `git version 2.39.5 (Apple Git-154)`, but does in 2.51.0, which I
>> installed with homebrew. (If this is a packaging error, I'll happily
>> report to homebrew.)
>
> That is definitely weird, and not something I'd expect if it's just a
> case collision. Is it possible for you to build Git from source? If so,
> and the problem happens with your build of 2.51.0 but not v2.39.5, it
> would be very enlightening to see the results of "git bisect". We can
> provide more guidance if you need with that process.
I bisected (git 2.39.5 built from source _also_ doesn't have this issue), and found the first bad commit:
0e358de64a9e014575d11ef884bfc9beb931e37f is the first bad commit
commit 0e358de64a9e014575d11ef884bfc9beb931e37f
Author: Karthik Nayak <karthik.188@gmail.com>
Date: Mon May 19 11:58:07 2025 +0200
fetch: use batched reference updates
The reference updates performed as a part of 'git-fetch(1)', take place
one at a time. For each reference update, a new transaction is created
and committed. This is necessary to ensure we can allow individual
updates to fail without failing the entire command. The command also
supports an '--atomic' mode, which uses a single transaction to update
all of the references. But this mode has an all-or-nothing approach,
where if a single update fails, all updates would fail.
CONFIDENTIALITY NOTICE AND DISCLAIMER : This telecommunication, including any and all attachments, contains confidential information intended only for the person(s) to whom it is addressed. Any dissemination, distribution, copying or disclosure is strictly prohibited and is not a waiver of confidentiality. If you have received this telecommunication in error, please notify the sender immediately by return electronic mail and delete the message from your inbox and deleted items folders. This telecommunication does not constitute an express or implied agreement to conduct transactions by electronic means, nor does it constitute a contract offer, a contract amendment or an acceptance of a contract offer. Contract terms contained in this telecommunication are subject to legal review and the completion of formal documentation and are not binding until same is confirmed in writing and has been signed by an authorized signatory.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-22 8:01 ` Karthik Nayak
@ 2025-08-22 17:47 ` Junio C Hamano
2025-08-28 13:51 ` Karthik Nayak
0 siblings, 1 reply; 16+ messages in thread
From: Junio C Hamano @ 2025-08-22 17:47 UTC (permalink / raw)
To: Karthik Nayak
Cc: Patrick Steinhardt, Jeff King, Joe Drew, git@vger.kernel.org
Karthik Nayak <karthik.188@gmail.com> writes:
> 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;
> }
> }
We assume that the existing lock is what _we_ created to lock the
ref in the other case, not somebody else locked-and-died some time
ago, or somebody else locked-and-about-to-update-competing-with-us?
Without this change we'd return REF_TRANSACTION_ERROR_GENERIC; does
the caller treat NAME_CONFLICT any specially? Or is the "fix" you
talk about just about giving a different message and no other
behaviour changes involved? I guess a more specific message that is
99% of the time more correct is an improvement over an overly
generic "some error happened" message. But I thought the original
issue was that the user cannot make any progress when the ref
updates are transactional. Does returning NAME_CONFLICT from here
tell the machinery that we are allowed to break transactional
semantics somehow?
In any case, I wonder if refs_verify_refnames_available() should
notice that we are using files backend on a case challenged
filesystem, and change the behaviour a bit. This additional check
needs to be implemented as a backend call via refs->be->something()
to tighten the outcome. It appears to me that the function in the
current form does not even notice a D/F conflict when there is a
branch 'd' and the transaction requests to create a new branch 'D/f'
on a case challenged system if files backend is in use, since the
function is in the generic layer and behaves case sensitively (which
is the right thing to do---we are talking about detecting backend
specific glitches here).
Thanks.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-20 21:33 ` Jeff King
2025-08-21 7:15 ` Patrick Steinhardt
2025-08-22 13:28 ` Joe Drew
@ 2025-08-26 11:19 ` Jeff King
2025-09-02 10:55 ` Patrick Steinhardt
2 siblings, 1 reply; 16+ messages in thread
From: Jeff King @ 2025-08-26 11:19 UTC (permalink / raw)
To: git; +Cc: Patrick Steinhardt, Joe Drew, Dave Evans
On Wed, Aug 20, 2025 at 05:33:23PM -0400, Jeff King wrote:
> If so, and assuming you're on a case-insensitive filesystem, then the
> lock files would collide. You wouldn't see anything after the fact
> because git-fetch itself would create the colliding lockfile, and then
> clean it up after hitting the fatal error.
>
> If that is the case, you can try using the reftables backend in v2.51.0.
> It doesn't use the filesystem for its ref storage or locking. Something
> like:
>
> git init --bare --ref-format=reftable
The response below came to me off-list. Here it is quoted with my reply:
On Sun, Aug 24, 2025 at 05:03:20PM +0100, Dave Evans wrote:
> I'm sorry but I do not have an email client I could use to post to the
> git mailing list.
> Please could you post my thoughts on this to the list.
>
> https://lore.kernel.org/git/20250820213323.GA1667633@coredump.intra.peff.net/
>
> I use git 2.51.0 built using Macports on a very old version of macOS
>
> There are a couple of repos on github that were showing this problem:
> vectorgraphics/asymptote
> ghc/ghc
>
> Both of them were bare clones.
>
> I applied --ref-format=reftable to the vectorgraphics/asymptote repo
> and a fetch
> went through to the end successfully
>
> The only snag I can see is that cgit no longer works. It says :
> Failed to open github/vectorgraphics/asymptote: No such file or directory
>
> The version of cgit is about 5 years old
I think that's all expected. Unlike most systems which call Git commands
like for-each-ref, etc, to access the ref store, cgit is linked directly
against Git's C code (something we don't support, but the cgit authors
accepted as a risk). So an old version of cgit will link against an old
version of Git, and won't know about reftable at all.
It _might_ not even be able to detect the directory as a git repo,
though I thought the reftable format was designed to let even old
versions of Git see the repo (e.g., the dummy value in HEAD).
-Peff
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-22 17:47 ` Junio C Hamano
@ 2025-08-28 13:51 ` Karthik Nayak
2025-08-28 16:16 ` Junio C Hamano
0 siblings, 1 reply; 16+ messages in thread
From: Karthik Nayak @ 2025-08-28 13:51 UTC (permalink / raw)
To: Junio C Hamano
Cc: Patrick Steinhardt, Jeff King, Joe Drew, git@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 3912 bytes --]
Junio C Hamano <gitster@pobox.com> writes:
> Karthik Nayak <karthik.188@gmail.com> writes:
>
>> 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;
>> }
>> }
>
Let me preface my response by saying that in my quick to respond bug
fix, I think the actual assigned error should be
'REF_TRANSACTION_ERROR_CREATE_EXISTS'.
> We assume that the existing lock is what _we_ created to lock the
> ref in the other case, not somebody else locked-and-died some time
> ago, or somebody else locked-and-about-to-update-competing-with-us?
>
We don't really change the path of exit, but rather just categorize the
error. So by marking it as 'REF_TRANSACTION_ERROR_CREATE_EXISTS', we
don't really say what kind of error it is.
In batched updates, the transaction allows failures unless a GENERIC
error is observed, wherein the transaction would fail. By marking the
error as 'REF_TRANSACTION_ERROR_CREATE_EXISTS', we allow batched updates
to allow this failure and carry on. Which I think it makes sense for all
the scenarios:
- existing lock created by us due to being on a case insensitive FS
- somebody else locked-and-died some time ago
- somebody else locked-and-about-to-update-competing-with-us
> Without this change we'd return REF_TRANSACTION_ERROR_GENERIC; does
> the caller treat NAME_CONFLICT any specially? Or is the "fix" you
> talk about just about giving a different message and no other
> behaviour changes involved? I guess a more specific message that is
> 99% of the time more correct is an improvement over an overly
> generic "some error happened" message. But I thought the original
> issue was that the user cannot make any progress when the ref
> updates are transactional. Does returning NAME_CONFLICT from here
> tell the machinery that we are allowed to break transactional
> semantics somehow?
>
Yes, without this, we'd return REF_TRANSACTION_ERROR_GENERIC. With this
change, we'd return REF_TRANSACTION_ERROR_CREATE_EXISTS.
This error type is bubbled up to `files_transaction_prepare()` which
tries to lock each reference update by calling `lock_ref_for_update()`.
So if the locking fails, we check if the rejection type can be ignored,
which is done by calling `ref_transaction_maybe_set_rejected()`.
Only during batched updates would errors be ignore and only for
non-generic errors. So this change would specifically only apply for
batched updates. Currently that is used by:
1. git fetch
2. git receive-pack
3. git update-ref --batch-updates
And for all three scenarios I think it makes sense to add this in.
> In any case, I wonder if refs_verify_refnames_available() should
> notice that we are using files backend on a case challenged
> filesystem, and change the behaviour a bit. This additional check
> needs to be implemented as a backend call via refs->be->something()
> to tighten the outcome. It appears to me that the function in the
> current form does not even notice a D/F conflict when there is a
> branch 'd' and the transaction requests to create a new branch 'D/f'
> on a case challenged system if files backend is in use, since the
> function is in the generic layer and behaves case sensitively (which
> is the right thing to do---we are talking about detecting backend
> specific glitches here).
>
> Thanks.
>
Absolutely, this whole thing with the files backend and case-insensitive
file-systems is a mess. Yes we'd need to go around and fix that too.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 690 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-28 13:51 ` Karthik Nayak
@ 2025-08-28 16:16 ` Junio C Hamano
2025-09-01 18:17 ` Karthik Nayak
0 siblings, 1 reply; 16+ messages in thread
From: Junio C Hamano @ 2025-08-28 16:16 UTC (permalink / raw)
To: Karthik Nayak
Cc: Patrick Steinhardt, Jeff King, Joe Drew, git@vger.kernel.org
Karthik Nayak <karthik.188@gmail.com> writes:
> This error type is bubbled up to `files_transaction_prepare()` which
> tries to lock each reference update by calling `lock_ref_for_update()`.
> So if the locking fails, we check if the rejection type can be ignored,
> which is done by calling `ref_transaction_maybe_set_rejected()`.
>
> Only during batched updates would errors be ignore and only for
> non-generic errors. So this change would specifically only apply for
> batched updates. Currently that is used by:
>
> 1. git fetch
> 2. git receive-pack
> 3. git update-ref --batch-updates
>
> And for all three scenarios I think it makes sense to add this in.
Thanks for an extra explanation.
These pieces of information would be necessary in the proposed log
message when it becomes a real patch.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-28 16:16 ` Junio C Hamano
@ 2025-09-01 18:17 ` Karthik Nayak
0 siblings, 0 replies; 16+ messages in thread
From: Karthik Nayak @ 2025-09-01 18:17 UTC (permalink / raw)
To: Junio C Hamano
Cc: Patrick Steinhardt, Jeff King, Joe Drew, git@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 975 bytes --]
Junio C Hamano <gitster@pobox.com> writes:
> Karthik Nayak <karthik.188@gmail.com> writes:
>
>> This error type is bubbled up to `files_transaction_prepare()` which
>> tries to lock each reference update by calling `lock_ref_for_update()`.
>> So if the locking fails, we check if the rejection type can be ignored,
>> which is done by calling `ref_transaction_maybe_set_rejected()`.
>>
>> Only during batched updates would errors be ignore and only for
>> non-generic errors. So this change would specifically only apply for
>> batched updates. Currently that is used by:
>>
>> 1. git fetch
>> 2. git receive-pack
>> 3. git update-ref --batch-updates
>>
>> And for all three scenarios I think it makes sense to add this in.
>
> Thanks for an extra explanation.
>
> These pieces of information would be necessary in the proposed log
> message when it becomes a real patch.
Yup. I will send it in soon. Was a bit busy last week with the OSSE and
Git mini summit.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 690 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: "lock file exists" when fetching in bare clone of repository
2025-08-26 11:19 ` Jeff King
@ 2025-09-02 10:55 ` Patrick Steinhardt
0 siblings, 0 replies; 16+ messages in thread
From: Patrick Steinhardt @ 2025-09-02 10:55 UTC (permalink / raw)
To: Jeff King; +Cc: git, Joe Drew, Dave Evans
On Tue, Aug 26, 2025 at 07:19:52AM -0400, Jeff King wrote:
> On Wed, Aug 20, 2025 at 05:33:23PM -0400, Jeff King wrote:
> > I'm sorry but I do not have an email client I could use to post to the
> > git mailing list.
> > Please could you post my thoughts on this to the list.
> >
> > https://lore.kernel.org/git/20250820213323.GA1667633@coredump.intra.peff.net/
> >
> > I use git 2.51.0 built using Macports on a very old version of macOS
> >
> > There are a couple of repos on github that were showing this problem:
> > vectorgraphics/asymptote
> > ghc/ghc
> >
> > Both of them were bare clones.
> >
> > I applied --ref-format=reftable to the vectorgraphics/asymptote repo
> > and a fetch
> > went through to the end successfully
> >
> > The only snag I can see is that cgit no longer works. It says :
> > Failed to open github/vectorgraphics/asymptote: No such file or directory
> >
> > The version of cgit is about 5 years old
>
> I think that's all expected. Unlike most systems which call Git commands
> like for-each-ref, etc, to access the ref store, cgit is linked directly
> against Git's C code (something we don't support, but the cgit authors
> accepted as a risk). So an old version of cgit will link against an old
> version of Git, and won't know about reftable at all.
>
> It _might_ not even be able to detect the directory as a git repo,
> though I thought the reftable format was designed to let even old
> versions of Git see the repo (e.g., the dummy value in HEAD).
Yeah, in theory old versions of Git should still be able to discover the
Git repository. They should bail out due to the "refstorage" extension,
but other than that all files that need to exist for Git to discover the
repository still exist with the reftable backend.
If that's not the case this is a bug we'd have to fix.
Patrick
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2025-09-02 10:55 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-20 20:54 "lock file exists" when fetching in bare clone of repository Joe Drew
2025-08-20 21:33 ` Jeff King
2025-08-21 7:15 ` Patrick Steinhardt
2025-08-21 7:27 ` Jeff King
2025-08-21 10:09 ` Patrick Steinhardt
2025-08-21 16:05 ` Junio C Hamano
2025-08-22 6:13 ` Patrick Steinhardt
2025-08-22 8:01 ` Karthik Nayak
2025-08-22 17:47 ` Junio C Hamano
2025-08-28 13:51 ` Karthik Nayak
2025-08-28 16:16 ` Junio C Hamano
2025-09-01 18:17 ` Karthik Nayak
2025-08-21 15:47 ` Junio C Hamano
2025-08-22 13:28 ` Joe Drew
2025-08-26 11:19 ` Jeff King
2025-09-02 10:55 ` Patrick Steinhardt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).