{"thread":{"id":"59217","subject":"[RFC] fetch: support hideRefs to speed up connectivity checks","startedAt":"2023-02-09T12:29:45Z","lastAt":"2023-02-16T01:32:40Z","messageCount":11,"participants":["Eric Wong","Jonathan Tan","Junio C Hamano","Jeff King","Philip Oakley"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"471851","messageId":"20230209122857.M669733@dcvr","threadId":"59217","inReplyTo":null,"subject":"[RFC] fetch: support hideRefs to speed up connectivity checks","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2023-02-09T12:28:57Z","receivedAt":"2023-02-09T12:29:45Z","isPatch":false,"sender":{"key":"e@80x24.org","avatar":null},"body":"Not sure if this is the right way to go about this...\nIf it's close, maybe --exclude-hidden=fetch can be supported.\nI'm using `receive' for now to minimize the change.\n\nWith roughly 800 remotes all fetching to their own refs/remotes/$REMOTE/*\nisland, the connectivity check[1] gets expensive for each fetch.\n\nTo do a no-op fetch on one $REMOTE out of hundreds, hideRefs now\nallows the no-op fetch to take ~30 seconds instead of ~20 minutes\non a noisy, RAM-constrained machine (localhost, so no network latency):\n\n   git -c transfer.hideRefs=refs \\\n\t-c transfer.hideRefs='!refs/remotes/$REMOTE/' \\\n\tfetch $REMOTE\n\nI initially considered passing --negotiation-tip OIDs, but this seems\nlike an easier solution as I'm not yet familiar with this code\nand prefer to avoid writing too much C.\n\n[1] `git rev-list --objects --stdin --not --all --quiet --alternate-refs'\n    gets painful w/o enough RAM to cache the repo, even on a SATA-2 SSD.\n---\n builtin/fetch.c | 2 ++\n 1 file changed, 2 insertions(+)\n\ndiff --git a/builtin/fetch.c b/builtin/fetch.c\nindex 12978622d5..473d99fd26 100644\n--- a/builtin/fetch.c\n+++ b/builtin/fetch.c\n@@ -1131,6 +1131,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,\n \tif (!connectivity_checked) {\n \t\tstruct check_connected_options opt = CHECK_CONNECTED_INIT;\n \n+\t\topt.exclude_hidden_refs_section = \"receive\";\n \t\trm = ref_map;\n \t\tif (check_connected(iterate_ref_map, &rm, &opt)) {\n \t\t\trc = error(_(\"%s did not send all necessary objects\\n\"), url);\n@@ -1324,6 +1325,7 @@ static int check_exist_and_connected(struct ref *ref_map)\n \t}\n \n \topt.quiet = 1;\n+\topt.exclude_hidden_refs_section = \"receive\";\n \treturn check_connected(iterate_ref_map, &rm, &opt);\n }\n \n"},{"id":"471947","messageId":"20230210214951.684909-1-jonathantanmy@google.com","threadId":"59217","inReplyTo":"20230209122857.M669733@dcvr","subject":"Re: [RFC] fetch: support hideRefs to speed up connectivity checks","fromName":"Jonathan Tan","fromEmail":"jonathantanmy@google.com","sentAt":"2023-02-10T21:49:51Z","receivedAt":"2023-02-10T21:50:00Z","isPatch":false,"sender":{"key":"jonathantanmy@fastmail.com","avatar":null},"body":"Eric Wong <e@80x24.org> writes:\n>    git -c transfer.hideRefs=refs \\\n> \t-c transfer.hideRefs='!refs/remotes/$REMOTE/' \\\n> \tfetch $REMOTE\n> \n> I initially considered passing --negotiation-tip OIDs, but this seems\n> like an easier solution as I'm not yet familiar with this code\n> and prefer to avoid writing too much C.\n\n--negotiation-tip supports ref name globs too. Would that be sufficient\nfor your purposes?\n \n"},{"id":"471949","messageId":"20230210215910.M7535@dcvr","threadId":"59217","inReplyTo":"20230210214951.684909-1-jonathantanmy@google.com","subject":"Re: [RFC] fetch: support hideRefs to speed up connectivity checks","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2023-02-10T21:59:09Z","receivedAt":"2023-02-10T21:59:12Z","isPatch":false,"sender":{"key":"e@80x24.org","avatar":null},"body":"Jonathan Tan <jonathantanmy@google.com> wrote:\n> Eric Wong <e@80x24.org> writes:\n> >    git -c transfer.hideRefs=refs \\\n> > \t-c transfer.hideRefs='!refs/remotes/$REMOTE/' \\\n> > \tfetch $REMOTE\n> > \n> > I initially considered passing --negotiation-tip OIDs, but this seems\n> > like an easier solution as I'm not yet familiar with this code\n> > and prefer to avoid writing too much C.\n> \n> --negotiation-tip supports ref name globs too. Would that be sufficient\n> for your purposes?\n\nYes, I tried using globs but didn't want to figure out how to\npass the resulting OIDs to rev-list.\n"},{"id":"471952","messageId":"xmqq1qmxgmed.fsf@gitster.g","threadId":"59217","inReplyTo":"20230209122857.M669733@dcvr","subject":"Re: [RFC] fetch: support hideRefs to speed up connectivity checks","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-02-10T22:56:26Z","receivedAt":"2023-02-10T22:56:30Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Wong <e@80x24.org> writes:\n\n> Not sure if this is the right way to go about this...\n> If it's close, maybe --exclude-hidden=fetch can be supported.\n\nYeah, why not.\n\nI however notice error handling in the codepath that deals with\n\"--exclude-hidden\" is  a bit sloppy.\n\nrefs.c::parse_hide_refs_config() is nice enough to diagnose a\nmalformed transfer.hiderefs configuration as an error by returning\n-1, and revision.c::hide_refs_config() propagates such an error up,\nbut revision.c::exclude_hidden_refs() ignores the error from\ngit_config(), and revision.c::handle_revision_pseudo_opt() ignores\nany error from exclude_hidden_refs() anyway.\n\nWe may want to tighten it a bit before (ab)using the option in more\ncontexts.\n\nThanks.\n"},{"id":"471975","messageId":"20230211075333.M933000@dcvr","threadId":"59217","inReplyTo":"xmqq1qmxgmed.fsf@gitster.g","subject":"Re: [RFC] fetch: support hideRefs to speed up connectivity checks","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2023-02-11T07:53:33Z","receivedAt":"2023-02-11T07:53:38Z","isPatch":false,"sender":{"key":"e@80x24.org","avatar":null},"body":"Junio C Hamano <gitster@pobox.com> wrote:\n> I however notice error handling in the codepath that deals with\n> \"--exclude-hidden\" is  a bit sloppy.\n> \n> refs.c::parse_hide_refs_config() is nice enough to diagnose a\n> malformed transfer.hiderefs configuration as an error by returning\n> -1, and revision.c::hide_refs_config() propagates such an error up,\n> but revision.c::exclude_hidden_refs() ignores the error from\n> git_config(), and revision.c::handle_revision_pseudo_opt() ignores\n> any error from exclude_hidden_refs() anyway.\n\nNot sure I follow.  exclude_hidden_refs() either dies or calls\ngit_config().  git_config() calls repo_config(), then\nconfigset_iter().  configset_iter() will git_die_config_linenr()\nif `fn' (hide_refs_config() in this case) returns < 0.\n\n> We may want to tighten it a bit before (ab)using the option in more\n> contexts.\n> \n> Thanks.\n"},{"id":"471984","messageId":"xmqqv8k8dmz0.fsf@gitster.g","threadId":"59217","inReplyTo":"20230211075333.M933000@dcvr","subject":"Re: [RFC] fetch: support hideRefs to speed up connectivity checks","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-02-11T19:24:35Z","receivedAt":"2023-02-11T19:24:39Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Wong <e@80x24.org> writes:\n\n> Junio C Hamano <gitster@pobox.com> wrote:\n>> I however notice error handling in the codepath that deals with\n>> \"--exclude-hidden\" is  a bit sloppy.\n>> \n>> refs.c::parse_hide_refs_config() is nice enough to diagnose a\n>> malformed transfer.hiderefs configuration as an error by returning\n>> -1, and revision.c::hide_refs_config() propagates such an error up,\n>> but revision.c::exclude_hidden_refs() ignores the error from\n>> git_config(), and revision.c::handle_revision_pseudo_opt() ignores\n>> any error from exclude_hidden_refs() anyway.\n>\n> Not sure I follow.  exclude_hidden_refs() either dies or calls\n> git_config().  git_config() calls repo_config(), then\n> configset_iter().  configset_iter() will git_die_config_linenr()\n> if `fn' (hide_refs_config() in this case) returns < 0.\n\nSomehow I had this wishful thinking that the return value from\ngit_config() can be checked and the caller can handle the error more\ngracefully, but its return type is void.  We'll die when we see a\nbad configuration but only when we see \"--exclude-hidden\", which is\nwhen we need a valid value from there.  That is how it should work,\nso I am now happier.\n\nThanks.\n"},{"id":"471989","messageId":"20230212090426.M558990@dcvr","threadId":"59217","inReplyTo":"20230209122857.M669733@dcvr","subject":"[PATCH v2] fetch: support hideRefs to speed up connectivity checks","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2023-02-12T09:04:26Z","receivedAt":"2023-02-12T09:04:32Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"With roughly 800 remotes all fetching into their own\nrefs/remotes/$REMOTE/* island, the connectivity check[1] gets\nexpensive for each fetch on systems which lack sufficient RAM to\ncache objects.\n\nTo do a no-op fetch on one $REMOTE out of hundreds, hideRefs now\nallows the no-op fetch to take ~30 seconds instead of ~20 minutes\non a noisy, RAM-constrained machine (localhost, so no network latency):\n\n   git -c fetch.hideRefs=refs \\\n\t-c fetch.hideRefs='!refs/remotes/$REMOTE/' \\\n\tfetch $REMOTE\n\n[1] `git rev-list --objects --stdin --not --all --quiet --alternate-refs'\n\nSigned-off-by: Eric Wong <e@80x24.org>\n---\n Sidenote: I'm curious about the reason $(pwd) is used in some\n places while $PWD seems fine in others, so it doesn't seem to be\n a portability problem.  I chose $PWD since it's faster.\n\n Documentation/git-rev-parse.txt    | 9 +++++----\n Documentation/rev-list-options.txt | 9 +++++----\n builtin/fetch.c                    | 2 ++\n builtin/rev-list.c                 | 2 +-\n revision.c                         | 3 ++-\n t/t5510-fetch.sh                   | 9 +++++++++\n t/t6018-rev-list-glob.sh           | 2 +-\n t/t6021-rev-list-exclude-hidden.sh | 2 +-\n 8 files changed, 26 insertions(+), 12 deletions(-)\n\ndiff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\nindex bcd80692870..f26a7591e37 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -197,10 +197,11 @@ respectively, and they must begin with `refs/` when applied to `--glob`\n or `--all`. If a trailing '/{asterisk}' is intended, it must be given\n explicitly.\n \n---exclude-hidden=[receive|uploadpack]::\n-\tDo not include refs that would be hidden by `git-receive-pack` or\n-\t`git-upload-pack` by consulting the appropriate `receive.hideRefs` or\n-\t`uploadpack.hideRefs` configuration along with `transfer.hideRefs` (see\n+--exclude-hidden=[fetch|receive|uploadpack]::\n+\tDo not include refs that would be hidden by `git-fetch`,\n+\t`git-receive-pack` or `git-upload-pack` by consulting the appropriate\n+\t`fetch.hideRefs`, `receive.hideRefs` or `uploadpack.hideRefs`\n+\tconfiguration along with `transfer.hideRefs` (see\n \tlinkgit:git-config[1]). This option affects the next pseudo-ref option\n \t`--all` or `--glob` and is cleared after processing them.\n \ndiff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\nindex ff68e484069..5e7f3c51792 100644\n--- a/Documentation/rev-list-options.txt\n+++ b/Documentation/rev-list-options.txt\n@@ -195,10 +195,11 @@ respectively, and they must begin with `refs/` when applied to `--glob`\n or `--all`. If a trailing '/{asterisk}' is intended, it must be given\n explicitly.\n \n---exclude-hidden=[receive|uploadpack]::\n-\tDo not include refs that would be hidden by `git-receive-pack` or\n-\t`git-upload-pack` by consulting the appropriate `receive.hideRefs` or\n-\t`uploadpack.hideRefs` configuration along with `transfer.hideRefs` (see\n+--exclude-hidden=[fetch|receive|uploadpack]::\n+\tDo not include refs that would be hidden by `git-fetch`,\n+\t`git-receive-pack` or `git-upload-pack` by consulting the appropriate\n+\t`fetch.hideRefs`, `receive.hideRefs` or `uploadpack.hideRefs`\n+\tconfiguration along with `transfer.hideRefs` (see\n \tlinkgit:git-config[1]). This option affects the next pseudo-ref option\n \t`--all` or `--glob` and is cleared after processing them.\n \ndiff --git a/builtin/fetch.c b/builtin/fetch.c\nindex 12978622d51..2763dd969bb 100644\n--- a/builtin/fetch.c\n+++ b/builtin/fetch.c\n@@ -1131,6 +1131,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,\n \tif (!connectivity_checked) {\n \t\tstruct check_connected_options opt = CHECK_CONNECTED_INIT;\n \n+\t\topt.exclude_hidden_refs_section = \"fetch\";\n \t\trm = ref_map;\n \t\tif (check_connected(iterate_ref_map, &rm, &opt)) {\n \t\t\trc = error(_(\"%s did not send all necessary objects\\n\"), url);\n@@ -1324,6 +1325,7 @@ static int check_exist_and_connected(struct ref *ref_map)\n \t}\n \n \topt.quiet = 1;\n+\topt.exclude_hidden_refs_section = \"fetch\";\n \treturn check_connected(iterate_ref_map, &rm, &opt);\n }\n \ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex d42db0b0cc9..2ab3efd233b 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -38,7 +38,7 @@ static const char rev_list_usage[] =\n \"    --tags\\n\"\n \"    --remotes\\n\"\n \"    --stdin\\n\"\n-\"    --exclude-hidden=[receive|uploadpack]\\n\"\n+\"    --exclude-hidden=[fetch|receive|uploadpack]\\n\"\n \"    --quiet\\n\"\n \"  ordering output:\\n\"\n \"    --topo-order\\n\"\ndiff --git a/revision.c b/revision.c\nindex 21f5f572c22..50940699e4a 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1574,7 +1574,8 @@ void exclude_hidden_refs(struct ref_exclusions *exclusions, const char *section)\n {\n \tstruct exclude_hidden_refs_cb cb;\n \n-\tif (strcmp(section, \"receive\") && strcmp(section, \"uploadpack\"))\n+\tif (strcmp(section, \"fetch\") && strcmp(section, \"receive\") &&\n+\t\t\tstrcmp(section, \"uploadpack\"))\n \t\tdie(_(\"unsupported section for hidden refs: %s\"), section);\n \n \tif (exclusions->hidden_refs_configured)\ndiff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh\nindex c0b745e33b8..287d6c3a8af 100755\n--- a/t/t5510-fetch.sh\n+++ b/t/t5510-fetch.sh\n@@ -1163,6 +1163,15 @@ test_expect_success '--no-show-forced-updates' '\n \t)\n '\n \n+for section in fetch transfer\n+do\n+\ttest_expect_success \"$section.hideRefs affects connectivity check\" '\n+\t\tGIT_TRACE=\"$PWD\"/trace git -c $section.hideRefs=refs -c \\\n+\t\t\t$section.hideRefs=\"!refs/tags/\" fetch &&\n+\t\tgrep \"git rev-list .*--exclude-hidden=fetch\" trace\n+\t'\n+done\n+\n setup_negotiation_tip () {\n \tSERVER=\"$1\"\n \tURL=\"$2\"\ndiff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh\nindex aabf590dda6..67d523d4057 100755\n--- a/t/t6018-rev-list-glob.sh\n+++ b/t/t6018-rev-list-glob.sh\n@@ -187,7 +187,7 @@ test_expect_success 'rev-parse --exclude=ref with --remotes=glob' '\n \tcompare rev-parse \"--exclude=upstream/x --remotes=upstream/*\" \"upstream/one upstream/two\"\n '\n \n-for section in receive uploadpack\n+for section in fetch receive uploadpack\n do\n \ttest_expect_success \"rev-parse --exclude-hidden=$section with --all\" '\n \t\tcompare \"-c transfer.hideRefs=refs/remotes/ rev-parse\" \"--branches --tags\" \"--exclude-hidden=$section --all\"\ndiff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh\nindex 32b2b094138..e219ac86738 100755\n--- a/t/t6021-rev-list-exclude-hidden.sh\n+++ b/t/t6021-rev-list-exclude-hidden.sh\n@@ -21,7 +21,7 @@ test_expect_success 'invalid section' '\n \ttest_cmp expected err\n '\n \n-for section in receive uploadpack\n+for section in fetch receive uploadpack\n do\n \ttest_expect_success \"$section: passed multiple times\" '\n \t\techo \"fatal: --exclude-hidden= passed more than once\" >expected &&\n"},{"id":"472028","messageId":"Y+qjRZTn7DNib1uB@coredump.intra.peff.net","threadId":"59217","inReplyTo":"20230212090426.M558990@dcvr","subject":"Re: [PATCH v2] fetch: support hideRefs to speed up connectivity checks","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2023-02-13T20:53:25Z","receivedAt":"2023-02-13T20:53:30Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Feb 12, 2023 at 09:04:26AM +0000, Eric Wong wrote:\n\n>  Sidenote: I'm curious about the reason $(pwd) is used in some\n>  places while $PWD seems fine in others, so it doesn't seem to be\n>  a portability problem.  I chose $PWD since it's faster.\n\nIt sometimes matters; one is a Windows path (with \"C:\\\", etc) and one is\na Unix-style path. Many spots are happy with either type, but it\nsometimes bites us when doing string comparisons, or in a few specific\ncases. See\n\n  https://lore.kernel.org/git/d36d8b51-f2d7-a2f5-89ea-369f49556e10@kdbg.org/\n\nfor an example.\n\n-Peff\n"},{"id":"472037","messageId":"13cef8e7-71af-27a5-77a3-a08f75720d1a@iee.email","threadId":"59217","inReplyTo":"Y+qjRZTn7DNib1uB@coredump.intra.peff.net","subject":"Re: [PATCH v2] fetch: support hideRefs to speed up connectivity checks","fromName":"Philip Oakley","fromEmail":"philipoakley@iee.email","sentAt":"2023-02-13T23:30:35Z","receivedAt":"2023-02-13T23:30:41Z","isPatch":true,"sender":{"key":"philipoakley@iee.email","avatar":"https://avatars.githubusercontent.com/u/914343?v=4"},"body":"On 13/02/2023 20:53, Jeff King wrote:\n> On Sun, Feb 12, 2023 at 09:04:26AM +0000, Eric Wong wrote:\n>\n>>  Sidenote: I'm curious about the reason $(pwd) is used in some\n>>  places while $PWD seems fine in others, so it doesn't seem to be\n>>  a portability problem.  I chose $PWD since it's faster.\n> It sometimes matters; one is a Windows path (with \"C:\\\", etc) and one is\n> a Unix-style path. Many spots are happy with either type, but it\n> sometimes bites us when doing string comparisons, or in a few specific\n> cases. See\n>\n>   https://lore.kernel.org/git/d36d8b51-f2d7-a2f5-89ea-369f49556e10@kdbg.org/\n>\n> for an example.\n>\nThere is guidance in t/README L680-684 though it maybe not that easy to\nspot.\n\nA more recent patch was\nhttps://lore.kernel.org/git/4f5c5633-f5a2-3c99-329e-3057b8d447d2@kdbg.org/\nwith slightly more details.\n\nPhilip\n\n\n"},{"id":"472039","messageId":"Y+rmlcRoP1aMioTC@coredump.intra.peff.net","threadId":"59217","inReplyTo":"13cef8e7-71af-27a5-77a3-a08f75720d1a@iee.email","subject":"Re: [PATCH v2] fetch: support hideRefs to speed up connectivity checks","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2023-02-14T01:40:37Z","receivedAt":"2023-02-14T01:40:42Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Feb 13, 2023 at 11:30:35PM +0000, Philip Oakley wrote:\n\n> On 13/02/2023 20:53, Jeff King wrote:\n> > On Sun, Feb 12, 2023 at 09:04:26AM +0000, Eric Wong wrote:\n> >\n> >>  Sidenote: I'm curious about the reason $(pwd) is used in some\n> >>  places while $PWD seems fine in others, so it doesn't seem to be\n> >>  a portability problem.  I chose $PWD since it's faster.\n> > It sometimes matters; one is a Windows path (with \"C:\\\", etc) and one is\n> > a Unix-style path. Many spots are happy with either type, but it\n> > sometimes bites us when doing string comparisons, or in a few specific\n> > cases. See\n> >\n> >   https://lore.kernel.org/git/d36d8b51-f2d7-a2f5-89ea-369f49556e10@kdbg.org/\n> >\n> > for an example.\n> >\n> There is guidance in t/README L680-684 though it maybe not that easy to\n> spot.\n> \n> A more recent patch was\n> https://lore.kernel.org/git/4f5c5633-f5a2-3c99-329e-3057b8d447d2@kdbg.org/\n> with slightly more details.\n\nThanks, both explanations are much better than the one I found (my\ndigging in the archive consisted of \"I know JSixt has corrected me on\nthis at least once...\").\n\n-Peff\n"},{"id":"472177","messageId":"20230216013237.M252435@dcvr","threadId":"59217","inReplyTo":"Y+rmlcRoP1aMioTC@coredump.intra.peff.net","subject":"Re: [PATCH v2] fetch: support hideRefs to speed up connectivity checks","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2023-02-16T01:32:37Z","receivedAt":"2023-02-16T01:32:40Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Jeff King <peff@peff.net> wrote:\n> On Mon, Feb 13, 2023 at 11:30:35PM +0000, Philip Oakley wrote:\n> > On 13/02/2023 20:53, Jeff King wrote:\n> > > On Sun, Feb 12, 2023 at 09:04:26AM +0000, Eric Wong wrote:\n> > >\n> > >>  Sidenote: I'm curious about the reason $(pwd) is used in some\n> > >>  places while $PWD seems fine in others, so it doesn't seem to be\n> > >>  a portability problem.  I chose $PWD since it's faster.\n> > > It sometimes matters; one is a Windows path (with \"C:\\\", etc) and one is\n> > > a Unix-style path. Many spots are happy with either type, but it\n> > > sometimes bites us when doing string comparisons, or in a few specific\n> > > cases. See\n> > >\n> > >   https://lore.kernel.org/git/d36d8b51-f2d7-a2f5-89ea-369f49556e10@kdbg.org/\n> > >\n> > > for an example.\n> > >\n> > There is guidance in t/README L680-684 though it maybe not that easy to\n> > spot.\n> > \n> > A more recent patch was\n> > https://lore.kernel.org/git/4f5c5633-f5a2-3c99-329e-3057b8d447d2@kdbg.org/\n> > with slightly more details.\n> \n> Thanks, both explanations are much better than the one I found (my\n> digging in the archive consisted of \"I know JSixt has corrected me on\n> this at least once...\").\n\nThanks both.  Looks like my use of GIT_TRACE=\"$PWD\"/trace is\nfine and there's plenty of examples where $PWD is used for\nGIT_TRACE* in our test suite (`git grep GIT_TRACE.*PWD')\n\nAny comments on the actual change itself?  Thanks again.\n"}]}