Symlinks in Windows, MinGW, Git, and Cygwin

Symlinks are a commonly used feature in Linux and macOS, but Windows traditionally either hasn’t supported them (prior to Windows Vista) or has strictly limited their use. As a result, many cross-platform development tools, like Git for Windows, either didn’t support or didn’t enable symlink support on Windows.

All of this makes cross-platform development on Windows trickier. Fortunately, symlink support on current Windows is mature and functional. You do, however, have to jump through several extra hoops to make it work.

Configuring Windows

Make sure you’re running Windows 10 Creators Update or above. This is the first version to give the option of allowing users to create symlinks without needing UAC elevation. (Prior to that, any processes that needed to manipulate symlinks needed to be run as administrator; this extra step is both annoying and hurts security.)

Enable developer mode: Go under Settings, under Update & Security, under For developers, and set “Use developer features” to “Developer mode.” This is how you enable the Windows 10 Creators Update option of allowing users to create symlinks without UAC elevation.

As described in the Git for Windows documentation, you’ll also need to edit Windows’ local security policy to grant permissions to create symlinks. My personal preference is to use gpedit.msc, since that’s a standard Windows tool. It’s not installed with Home editions of Windows, but, as explained on AskVG, you can install it yourself using these commands.

dir /b C:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientExtensions-Package~3*.mum >Files.txt
dir /b C:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientTools-Package~3*.mum >>Files.txt
for /f %i in ('findstr /i . Files.txt 2^>nul') do dism /online /norestart /add-package:"C:\Windows\servicing\Packages\%i"
del Files.txt

Incidentally, in case you’re wondering why all of this is necessary, the concern was that symlinks could be a security risk:

Symbolic links (symlinks) can expose security vulnerabilities in applications that aren’t designed to handle symbolic links. - Microsoft TechNet

Although more than a little hand-wavy, this argument is not without merit. Even on Unix-like operating systems, which have had decades to get used to symlinks, the occasional symlink race vulnerability pops up, and Windows software had been developed with no experience or expectation of this feature.

Configuring MinGW, Cygwin, and Git

Now you need to configure your software to make use of Windows’ new features.

For MSYS / MinGW (this includes the command-line utilities that used in the git-bash shell), add an environment variable, MSYS, and make sure it contains winsymlinks:nativestrict. (If you don’t do this, then symlinks are “emulated” by copying files and directories. This can be surprising, to say the least.)

For Cygwin, add an environment variable, CYGWIN, and make sure it contains winsymlinks:nativestrict. See the Cygwin manual for details. (If you don’t do this, then Cygwin defaults to emulating symlinks by using special file contents that it understands but non-Cygwin software doesn’t.)

For Git for Windows, make sure that the core.symlinks config option is true. In a normal Git system, this would be done at the system level (git config --system core.symlinks true). However, Git for Windows adds an additional “super-system” configuration file, c:\\ProgramData\\Git\\config; this was where I had to update core.symlinks on my system. (This Stack Overflow answer describes c:\\ProgramData\\Git\\config better.)

For Subversion, you’re out of luck. Even though Windows supports symlinks, the Subversion libraries don’t have the necessary code to take advantage of this.

Is there any other relevant software that needs configuration to support Windows symlinks? Let me know on Twitter.

Update: If you’re looking for a Windows GUI to help you manage all of these symlinks, the Link Shell Extension is very useful. It allows you to create symlinks, junction points, and more by right-dragging items in Explorer.