git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: git tries to stat //HEAD when searching for a repo, leading to huge delays on Cygwin

From
Jeff King <peff@peff.net>
Date
Nov 3, 2017, 01:03 UTC
Message-ID
<20171103010300.3jwme4d6nbxnj6od@sigill.intra.peff.net>
In-Reply-To
<MWHPR21MB0159089DB91A30E5E5CFCB479E5C0@MWHPR21MB0159.namprd21.prod.outlook.com>
On Thu, Nov 02, 2017 at 11:45:55PM +0000, Andrew Baumann wrote:
Show 28 quoted lines
> I have a workaround for this, but someone on stack overflow [1]
> suggested reporting it upstream, so here you go:
> 
> I have a fancy shell prompt that executes "git rev-parse
> --is-inside-work-tree" to determine whether we're currently inside a
> working directory. This causes git to walk up the directory hierarchy
> looking for a containing git repo. For example, when invoked from my
> home directory, it stats the following paths, in order:
> 
> /home/me/.git
> /home/me/.git/HEAD
> /home/me/HEAD
> /home
> /home/.git
> /home/.git/HEAD
> /home/HEAD
> /
> /.git
> /.git/HEAD
> //HEAD
> 
> The last name (//HEAD) interacts badly with Cygwin, which interprets
> it as a UNC file share, and so demand-loads a bunch of extra DLLs and
> attempts to resolve/contact the server named HEAD. This obviously
> doesn't work too well, especially over a slow network link.
> 
> I've tested with the latest Cygwin git (2.15.0); this was also present
> in a prior version.

Interesting. I can reproduce on Linux (but of course "//HEAD" is cheap to look at there). It bisects to ce9b8aab5d (setup_git_directory_1(): avoid changing global state, 2017-03-13). Before that, the end of the strace for "git rev-parse --git-dir" looks like:

  chdir("..")                             = 0
  stat(".git", 0x7fffba398e00)            = -1 ENOENT (No such file or directory)
  lstat(".git/HEAD", 0x7fffba398dd0)      = -1 ENOENT (No such file or directory)
  lstat("./HEAD", 0x7fffba398dd0)         = -1 ENOENT (No such file or directory)
  write(2, "fatal: Not a git repository (or "..., 69) = 69
and after:
  stat("/.git", 0x7ffdb28b7eb0)           = -1 ENOENT (No such file or directory)
  lstat("/.git/HEAD", 0x7ffdb28b7e80)     = -1 ENOENT (No such file or directory)
  lstat("//HEAD", 0x7ffdb28b7e80)         = -1 ENOENT (No such file or directory)
  write(2, "fatal: Not a git repository (or "..., 69) = 69

Switching to using absolute paths rather than chdir-ing around is intentional for that commit, but it looks like we just need to special-case the construction of the root path.

Like this, perhaps:
diff --git a/setup.c b/setup.c
index 27a31de33f..5d0b6a88e3 100644
--- a/setup.c
+++ b/setup.c
@@ -283,7 +283,9 @@ int is_git_directory(const char *suspect)
 	size_t len;
 
 	/* Check worktree-related signatures */
-	strbuf_addf(&path, "%s/HEAD", suspect);
+	strbuf_addstr(&path, suspect);
+	strbuf_complete(&path, '/');
+	strbuf_addstr(&path, "HEAD");
 	if (validate_headref(path.buf))
 		goto done;
 

-Peff
Previous: Andrew BaumannNext: Johannes Schindelin
Message 2 of 6 in “git tries to stat //HEAD when searching for a repo, leading to huge delays on Cygwin”
  1. Andrew BaumannNov 2, 2017
  2. Jeff KingNov 3, 2017
  3. Johannes SchindelinNov 3, 2017
  4. Jeff KingNov 3, 2017
  5. setup.c: don't try to access '//HEAD' during repo discoverySZEDER Gábor, Nov 3, 2017
  6. Johannes SchindelinNov 3, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.