# [Bug Report] git config includeIf not traversing symlink subdirectories

3 messages from 2024-05-03 to 2024-05-04. Participants: Simon Thurston, brian m. carlson.
Thread: https://gitlist.dev/t/61417

## Simon Thurston, 2024-05-03 21:31

Subject: [Bug Report] git config includeIf not traversing symlink subdirectories
Message-ID: <CAKx51amU_c9EU+573RWDc0+w3V2u5TSk+mQhts1gYyKRhxGCzQ@mail.gmail.com>
URL: https://gitlist.dev/e/CAKx51amU_c9EU%2B573RWDc0%2Bw3V2u5TSk%2BmQhts1gYyKRhxGCzQ%40mail.gmail.com

```
Thank you for filling out a Git bug report!
Please answer the following questions to help us understand your issue.

What did you do before the bug happened? (Steps to reproduce your issue)
On Windows. Create a directory. Configre a gitconfig file to includeIf
gitdir that directory. Add any configuration you wish to the gitconfig
file pointed to by the includeif path. Inside the created directory,
create a symlink to a UNC Path/Network location. Change directory into
the symlinked directory. Run git config --show-origin on a configured
value.

What did you expect to happen? (Expected behavior)
The value configured in the includeIf path to be found.

What happened instead? (Actual behavior)
No configuration data found.

What's different between what you expected and what actually happened?
Git seems to be unable to traverse subdirectories that are symlinks to
include any git repositories stored inside them.

Anything else you want to add:
I am well aware that while running Windows 11 in a corporate
environment there is likely something silly that is stopping me from
doing something correctly within our Group Policy. However, I just
wanted to open a report in case that something is not working. The
workaround I had to do for this is to regular include the config file
I had written, which is not ideal, even though I am pretty sure that
the includeIfs I have after it should override it. I am interacting
with git through pwsh 7.4.2.

Please review the rest of the bug report below.
You can delete any lines you don't wish to share.


[System Info]
git version:
git version 2.45.0.windows.1
cpu: x86_64
built from commit: b5d0511969ccd9ab86395c37e5a7619d8b4e7c32
sizeof-long: 4
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon
uname: Windows 10.0 22635
compiler info: gnuc: 13.2
libc info: no libc information available
$SHELL (typically, interactive shell): <unset>


[Enabled Hooks]

```

## brian m. carlson, 2024-05-03 23:06

Subject: Re: [Bug Report] git config includeIf not traversing symlink subdirectories
Message-ID: <ZjVt5jtC8cKgWpqQ@tapette.crustytoothpaste.net>
URL: https://gitlist.dev/e/ZjVt5jtC8cKgWpqQ%40tapette.crustytoothpaste.net
In-Reply-To: <CAKx51amU_c9EU+573RWDc0+w3V2u5TSk+mQhts1gYyKRhxGCzQ@mail.gmail.com>

```
On 2024-05-03 at 21:31:59, Simon Thurston wrote:
> Thank you for filling out a Git bug report!
> Please answer the following questions to help us understand your issue.
> 
> What did you do before the bug happened? (Steps to reproduce your issue)
> On Windows. Create a directory. Configre a gitconfig file to includeIf
> gitdir that directory. Add any configuration you wish to the gitconfig
> file pointed to by the includeif path. Inside the created directory,
> create a symlink to a UNC Path/Network location. Change directory into
> the symlinked directory. Run git config --show-origin on a configured
> value.

I've included a shell script below that tries to provide a testcase for
your reproduction steps.  Since I'm on Linux, I don't have a UNC drive,
but I created a different location outside of the repository called
other-dir that simulates the same behaviour:

----
#!/bin/sh

tempdir=$(mktemp -d)
cd "$tempdir"
cat >config <<EOM
[includeIf "gitdir:$tempdir/dir/"]
    path = "$tempdir/other-config"
EOM
cat >other-config <<EOM
[user]
    name = "Foo Bar"
EOM

export GIT_CONFIG_GLOBAL="$tempdir/config"
mkdir "$tempdir/dir"
mkdir "$tempdir/other-dir"
cd "$tempdir/dir"
git init -b dev
echo "In dir ($PWD):"
git config -l --show-origin
ln -s ../other-dir other-dir
cd other-dir
echo "In symlink ($PWD):"
git config -l --show-origin
----

> What did you expect to happen? (Expected behavior)
> The value configured in the includeIf path to be found.
> 
> What happened instead? (Actual behavior)
> No configuration data found.
> 
> What's different between what you expected and what actually happened?
> Git seems to be unable to traverse subdirectories that are symlinks to
> include any git repositories stored inside them.

Assuming my reproduction steps are correct, this is expected.  Git
always determines the Git directory by resolving it to an absolute path
containing no symlinks with the equivalent of `realpath` on Linux or
`GetFinalPathNameByHandle` on Windows.  The fact that your working
directory contains a symlink doesn't mean that the destination of the
symlink is part of your repository.  In fact, if the destination of your
symlink is on another drive, it cannot be in your repository at all,
since Git cannot handle cross-drive repositories at all.  Since it's not
in the repository, the gitdir pattern won't match.

If I've misunderstood, could you help me understand better by providing
a small shell script that can reproduce the problem you're seeing, so
I can provide a better answer?
-- 
brian m. carlson (they/them or he/him)
Toronto, Ontario, CA

```

## brian m. carlson, 2024-05-04 01:06

Subject: Re: [Bug Report] git config includeIf not traversing symlink subdirectories
Message-ID: <ZjWKHJD50PNcWu5R@tapette.crustytoothpaste.net>
URL: https://gitlist.dev/e/ZjWKHJD50PNcWu5R%40tapette.crustytoothpaste.net
In-Reply-To: <B240544D-1695-4627-B7EC-5C9CA7716265@gmail.com>

```
[Please keep the list in CC so others can chime in.]

On 2024-05-03 at 23:41:14, Simon Thurston wrote:
> Thanks Brian. The issue I'm having is that I have two main development directories, for "home" and for "work". I have includeIf statements in my primary .gitconfig that sources different public/private keys for each subdirectory. Under the "work" subdirectory, I have folders for projects, and then a "Deploy" folder that contains symlinks to folders over the network, so I can quickly cd and git clone/pull to deploy things manually, as well as use with some CD powershell scripts I have. The important thing to note is that the directories that are symlinked to repositories.
> 
> In short, if I have an includeIf that encompasses a parent directory, any subdirectory symlink that points to a repository on a local server does not properly resolve to include the settings from the includeIf.
> 
> /work/Project/.git can be detected, but /work/Deploy/ProjectSymlink/.git cannot, and thus any includeIf statement that checks for repositories under /work/** does not properly detect the repositories that are symlinked.

Yes, I think this is intentional.  Git doesn't consider the repositories
which are on the UNC drive to be under /work/Deploy, because the
canonical path is not in that location.

> I have tried to get around this by adding an extra includeIf statement to include //the/direct/unc/path/** but that was not able to resolve properly either. Mapped network drives with drive letters also don't resolve, and the only workaround I had was to blanket apply the config file to every directory, which is not ideal for the environment I work in.

Yes, the mapped network drives will be resolved to the UNC path with
`GetPathNameByHandle`, which is why that syntax doesn't work.

> If the behavior around symlinks is intentional, then that is fine and can be worked around, but not being able to specify UNC style paths in the configs is something that makes it difficult to work on SMB shares with specific configs needed.

As I said, I don't use Windows except extremely incidentally, so it's
difficult for me to speak with any authority on UNC paths.  It's
possible that they are supported using a syntax I don't know about, or
it's possible that they simply don't work at all.  If it's the latter,
I'm sure we'd accept a patch to fix it.

What I might suggest is switching into one of the symlinked directories
and running `git rev-parse --absolute-git-dir`, which should show you
what Git thinks the directory is.  You can then write that path directly
in the configuration file, nothing that inside the double quotes,
backslashes must be escaped (so if the path is \\the\direct\unc\path,
you'd write '[includeIf "\\\\the\\direct\\unc\\path"]').  You may also
want to use gitdir/i if you're not already, since my guess is that your
paths are actually case-insensitive.

If that doesn't work, hopefully someone else more familiar than me with
Windows can speak more to this.
-- 
brian m. carlson (they/them or he/him)
Toronto, Ontario, CA

```
