Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error: could not symlink 'path1' to 'path2': Function not implemented #5517

Open
vwheeler63 opened this issue Mar 27, 2025 · 13 comments
Open

Comments

@vwheeler63
Copy link

vwheeler63 commented Mar 27, 2025

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)

I was trying to do a normal `git difftool -gd  hash1   hash2` -- this used to work perfectly.

What did you expect to happen? (Expected behavior)

BC4 (Beyond Compare 4) to launch in a directory-comparison session comparing the 2 commits.

What happened instead? (Actual behavior)

This:
$ git difftool -gd d604180 fc16efc
error: could not symlink 'E:/Dev/Clients/WGA/lvgl/vwheeler63/lvgl/docs/src/details/main-modules/draw/draw_descriptors.rst' to 'R:\TMPDIR/git-difftool.a04204/right/docs/src/details/main-modules/draw/draw_descriptors.rst': Function not implemented

I don't often need this, but when I do, I really need it, and I think it worked
perfectly 4-5 months ago (last time I did it).  (My memory on this timing is
vague—it might have been as much as 7 months ago.)

What's different between what you expected and what actually happened?

Instead of launching BC4, it issued this error message.

Anything else you want to add:

I'm using mintty on a Windows 10 x64 system (up to date as of today's date).

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.48.1.windows.1
cpu: x86_64
built from commit: 2bd190b
sizeof-long: 4
sizeof-size_t: 8
shell-path: D:/git-sdk-64-build-installers/usr/bin/sh

    <<<<  Note:  the above is a bit odd because I don't have a `D:` drive and no
    removable drive was mounted as `D:` when I executed `git bugreport` to gather
    this text.  In case it helps, the above `git difftool -gd` command was issued while
    the `E:` drive was the current drive, but I have never had trouble with it before,
    and have been using this command for years -- at least since 2018 with zero problems.

feature: fsmonitor--daemon
libcurl: 8.12.1
OpenSSL: OpenSSL 3.2.4 11 Feb 2025
zlib: 1.3.1
uname: Windows 10.0 19045
compiler info: gnuc: 14.2
libc info: no libc information available
$SHELL (typically, interactive shell): C:\Program Files\Git\usr\bin\bash.exe

[Enabled Hooks]

@rimrul
Copy link
Member

rimrul commented Mar 27, 2025

I assume you %TEMP% points to R:\TMPDIR?

What filesystems are E:\ and R:\?

@vwheeler63
Copy link
Author

vwheeler63 commented Mar 27, 2025

I assume you %TEMP% points to R:\TMPDIR?

That is correct.

What filesystems are E:\ and R:\?

E: is an SD drive -- NTFS -- it is a separate drive where I do most of my work it can be incrementally backed up every night, unlike my C: drive which doesn't change that often.

R: is a RAMDISK -- FAT32 -- used to save wear-and-tear on my SD drives. I have had this configuration since 2012, and it has been working for git difftool -gd hash1 hash2 since I started using git in 2018.

@rimrul
Copy link
Member

rimrul commented Mar 27, 2025

E: is an SD drive -- it is a separate drive so that it can be fully (incrementally) backed up every night.

I was less concerned about the underlying hardware, but how it was formatted (ReFS, FAT32, NTFS, ...), and in the case of R:\ wether it poentially was a ram disk, network share or something similar.

R: is a RAMDISK

I had a sneaking suspicion it might be.

@vwheeler63
Copy link
Author

I was less concerned about the underlying hardware, but how it was formatted (ReFS, FAT32, NTFS, ...)

E: NTFS
R: FAT32

@rimrul
Copy link
Member

rimrul commented Mar 27, 2025

Looking at 8241ae6#diff-34f226145d3399ac034db4d76355be47bd76a6b919058929124d82461205d11fL707-R722, it looks like the default for --symlinks was flipped in 2.49.0. and FAT32 doesn't support symlinks. you can probably work around that with --no-symlinks for now.

@vwheeler63
Copy link
Author

vwheeler63 commented Mar 27, 2025

Looking at 8241ae6#diff-34f226145d3399ac034db4d76355be47bd76a6b919058929124d82461205d11fL707-R722, it looks like the default for --symlinks was flipped in 2.49.0. and FAT32 doesn't support symlinks. you can probably work around that with --no-symlinks for now.

I'm glad there is a workaround. As a note (in case the git-scm team wasn't already aware of it): on this page: https://git-scm.com/docs/git-difftool it says:

...  --no-symlinks is the default on Windows.

so it would appear that documentation is out of sync with the executable? Or vice versa?

@dscho
Copy link
Member

dscho commented Mar 28, 2025

shell-path: D:/git-sdk-64-build-installers/usr/bin/sh

    <<<<  Note:  the above is a bit odd because I don't have a `D:` drive and no
    removable drive was mounted as `D:` when I executed `git bugreport` to gather
    this text.  In case it helps, the above `git difftool -gd` command was issued while
    the `E:` drive was the current drive, but I have never had trouble with it before,
    and have been using this command for years -- at least since 2018 with zero problems.

@vwheeler63 this information is unfortunately a bit misleading. I am not a fan of the git bugreport command, and this is one of the reasons: What it shows here are not the runtime settings, but the compile-time settings. The shell-path in particular does not affect how Git for Windows runs, as it will determine the path of the shell interpreter dynamically.

Also, is there any reason why you marked up your reply, not the output of git bugreport, as code (by prefixing/suffixing it with lines containing four backticks)? It's just a bit harder to read when marked up this way, my eyes stumbled over this.

As a note (in case the git-scm team wasn't already aware of it): on this page: https://git-scm.com/docs/git-difftool it says:

...  --no-symlinks is the default on Windows.

so it would appear that documentation is out of sync with the executable?

This note was introduced in 1f22934, when the statement was true.

However, when I converted this command from a Perl script (!) to a built-in written in portable C in 03831ef, I changed that to respect the core.symlinks variable, which is set by git init/git clone depending on the outcome of a simple test.

What core.symlinks does not do is to verify that symlinks are supported outside the worktree, and that includes the TMPDIR.

In the long run, I am fairly convinced you will want to reformat your RAM disk using ReFS (or NTFS), to avoid similar problems.

Having said that, the regression in 8241ae6 is real and needs to be addressed.

I have had this configuration since 2012, and it has been working for git difftool -gd hash1 hash2 since I started using git in 2018.

Now, this is curious. The core.symlinks of your worktree on the E: drive should be set to true, because you're using uname: Windows 10.0 19045 and that already supports symlink creation in Developer Mode. Or are you not running in Developer Mode?

@vwheeler63
Copy link
Author

vwheeler63 commented Mar 28, 2025

Hi, Johannes! I'm honored to speak with you!

I am not a fan of the git bugreport command, and this is one of the reasons: What it shows here are not the runtime settings, but the compile-time settings.

Ah! That explains that. Thank you.

...is there any reason why you marked up your reply, not the output of git bugreport, as code (by prefixing/suffixing it with lines containing four backticks)? It's just a bit harder to read when marked up this way, my eyes stumbled over this.

Fair question: my only intent was to indent the paragraph so that it showed I was commenting about the line above it. The 4 backticks was unintentional (I intended 3, and in retrospect, could merely have indented the paragraph—and the fact that the 4 backticks appeared twice was probably a copy-paste casualty).

...to respect the core.symlinks variable, which is set by git init/git clone depending on the outcome of a simple test.

What core.symlinks does not do is to verify that symlinks are supported outside the worktree, and that includes the TMPDIR.

That makes sense and is good to know. It also makes sense to do the test once and keep the result as a repository-configuration value—as opposed to doing the test with every command, if only for sake of limiting how often that overhead is incurred. (It's also quite orienting to see that in the C code [since I am just getting familiar with the project]. Thank you for that.)

In the long run, I am fairly convinced you will want to reformat your RAM disk using ReFS (or NTFS), to avoid similar problems.

In fact I thought about it, but decided against it. Reason: I have the RAM disk there and configured the way it is (FAT32 + Direct-IO access as opposed to through a SCSI driver) for speed. (Reason: I do a large amount of small-file generation and deletion every day [including web-browser caches] there to reduce wear-and-tear on my SD drives.) If being able to use symlinks was my priority, I would certainly use NTFS. (Even the newest version of my RAM disk software doesn't yet know about ReFS.) Though I will humbly admit: I do not know if I would notice the difference using NTFS.... **rolling eyes at self** Probably not.

Since there is no wear-and-tear concerns with doing actual file copies on a RAMDisk (as there is with SD drives), for now I will set a global core.symlinks configuration to false.

Having said that, the regression in 8241ae6 is real and needs to be addressed.

I'm thankful for that.

Now, this is curious. The core.symlinks of your worktree on the E: drive should be set to true, because you're using uname: Windows 10.0 19045 and that already supports symlink creation in Developer Mode. Or are you not running in Developer Mode?

I am indeed running in Developer Mode.

On a hunch, I went to look at the repository where I was working the last time I used git difftool -g --dir-diff and sure enough: core.symlinks = false, was set local to that repository. (I created the repository first locally [as opposed to cloning it], so I must have set it myself.) That explains why it worked (for me) previously and not yesterday (in a different repository, cloned, where core.symlinks is not set locally).

In Conclusion

I am happy to set a global core.symlinks configuration to false while I have this TEMP environment variable set to my RAM disk.

I just tried it and indeed, difftool is now working as it was before. 😄 (I have to say, I think difftool is one of the most powerful features of git!)

@vwheeler63
Copy link
Author

vwheeler63 commented Mar 28, 2025

Are there good reasons I have not yet thought of to reconsider using NTFS on my RAM drive?

(I was fascinated reading the commit message on 03831ef! Thank you for sharing that.)

@boimart1
Copy link

boimart1 commented Mar 28, 2025

I encountered this problem as well. difftool works fine in 2.48.1 but no longer works in 2.49.0.

This could also be related to 84f0bdc. git difftool uses the new create_symlink() when core.symlinks is set to true (difftool.c#L544). Maybe something in the change from symlink() to create_symlink() caused this problem?

eta: in my case, I'm on Windows 11, and my repository and my TEMP directory are both on C:, which uses NTFS. On 2.48.1, difftool -d --symlinks works works correctly.

@rimrul
Copy link
Member

rimrul commented Mar 28, 2025

git difftool uses the new create_symlink() when core.symlinks is set to true (difftool.c#L544).

create_symlink() is from 2019. https://github.com/git-for-windows/git/commit/51540f330c1/ It's really not that new.

@boimart1
Copy link

create_symlink() is from 2019. https://github.com/git-for-windows/git/commit/51540f330c1/ It's really not that new.

Ah... I saw the "2 weeks ago" in the commit I linked and assumed it was new. My bad.

In that case, I don't see why I'm getting different behaviors between 2.48.1 and 2.49.0, considering symlinks seem to be supported just fine when using 2.48.1.

@boimart1
Copy link

boimart1 commented Mar 28, 2025

I performed some more extensive tests, here are the differences between 2.48.1 and 2.49.0.

  • Using Windows 11 Pro 24H2, build 26100.3476.
  • Git was installed using choco install git --version=[version], and version was confirmed using git --version.
  • core.symlinks is always explicitly specified in my user .gitconfig file, and never in my local repository's .git/config file.
  • I ran git difftool -d [symlinks flag] master... for each of the following tests.
  • All failures have the same error message: "error: could not symlink '[path in repo]' to '[path in %TEMP%]': Function not implemented."

In short, it looks like no matter what, 2.49.0 is unable to create symlinks for difftool. I also find it interesting that both versions are unable to create symlinks for difftool when core.symlinks is false, as I would expect that to only affect the behaviour for symlinks in repositories.

core.symlinks symlinks flag Using Git 2.48.1 Using Git 2.49.0
false [not specified] Creates copies Creates copies
false --no-symlinks Creates copies Creates copies
false --symlinks Fails Fails
true [not specified] Creates symlinks Fails
true --no-symlinks Creates copies Creates copies
true --symlinks Creates symlinks Fails

(p.s. after reading through the prior discussions, I understand this isn't the same as the original problem reported by @vwheeler63, I just happened to get a similar error message on the same day 😅 )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants