Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
HOWTO: Use WSL and its Git in a mixed development environment

How to setup a development environment where Git from WSL integrates with native Windows applications, using the Windows home folder as the WSL home and using Git from WSL for all tools.

Note if using Git for Windows, or any tool on the Windows side that does not use Git from WSL then there will likely be problems with file permissions inside WSL.

Tools

These are the tools I use:

  • git (wsl) - Command line git from within WSL.
  • GitKraken (windows) - Git GUI, uses its own build-in git commands.
  • Fork (windows) - Git GUI, use with wslgit-fork-patch. Important! Follow the instructions here after WSL is installed!
  • KDiff3 (windows) - Diff/merge GUI tool, invoked from git inside wsl.
  • VSCode (windows)
  • wsltty (windows) - Terminal of choice, just download and install.

WSL Installation

  1. First time? Open PowerShell and run:

    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
  2. Download and install a distro from Windows Store, Command-Line or manually unpack and install (for Windows Server).

Important! Start WSL once directly after installing the distribution of choise to finish the installation.

For full details see https://docs.microsoft.com/en-us/windows/wsl/install-win10.

User Name and Password

When selecting a WSL user name you don't need to use the same name as your windows logon. The password can be anything but you must remember it since it will be used when sudo-ing.

The user name and password in WSL have nothing to do with the Windows user name and password, so changing your password in windows does not change your password in WSL, or vice versa.
The password you use in WSL is not critical for security since you still need to log on to your windows account to start WSL so it can be an easy to remember password.
However, if you enable access to your WSL via SSH and allow password authentication then your WSL password strength will be of importance. But don't allow password authentication, just use pubkey authentication.

WSL Setup

wsl.conf

In WSL, create (or edit) the file /etc/wsl.conf:

[automount]
enabled = true
root = /
options = "metadata,umask=022,fmask=111,case=off"

Restart all active WSL sessions, can be done from CMD: wsl -t Ubuntu-18.04

root = / changes the mount root for windows local drives to '/' instead of the default '/mnt/, so instead of C: mounted at '/mnt/c' it will be mounted at '/c'.

The metadata option will make it possible to set the owner and group of files using chown and modify read/write/execute permissions in WSL using chmod. See Chmod/Chown WSL Improvements for details.

case=off will make all directories created from within WSL to be case insensitive in the windows file system, because even if Windows is case sensitive the applications run on windows is not necessary case sensitive.

umask and fmask

The umask and fmask sets the default values of the permissions on files and directories oi mounted windows drives. The umask=022 option excludes write permission for group/others for files and directories, and the fmask=111 option excludes execution permission for user/group/others for files, making the default mask 644 on all windows drives mounted automatically by WSL. The permissions can be changed by using chmod, which will create metadata for a file containing the modified permissions.

Important! This will make ALL files and directories in /c have 644 as default permissions, meaning that it won't be possible to execute any applications or scripts in the windows drives unless you specifically add the execute permission from within WSL to that file using chmod +x file.exe.
Using chmod will add metadata to that file with the execution permission set allowing WSL to execute the file. If the file is replaced it will loose its metadata and you must do chmod again.

Wsltty is not working anymore!

After adding umask and fmask then wsltty will not start, the window just opens up and closes directly. This is because the execution bit is not set for wslbridge-backend anymore. To fix this open the default Ubuntu terminal and add the execution permission for wslbridge-backend which is located in AppData:

chmod +x /c/Users/<user.name>/AppData/Local/wsltty/bin/wslbridge-backend

(If you are not using your Windows profile)

Program Xyz.exe is not working anymore!

Add the execution permission for the application:

chmod +x /path/to/xyz.exe

Note that all files in '/c/Windows/', '/c/Program Files/' and '/c/Program Files (x86)/' requires the WSL terminal to be started as administrator to be able to modify the permissions.

Scripts does not work after git checkout!

When doing git-checkout from a windows tool and a script file is replaced then it might will loose its metadata, which means loosing the execution permission. If trying to execute the script you will get a Permission denied, and if doing a git diff you will just get a difference in mode:

$ git diff
diff --git a/myscript b/myscript
old mode 100755
new mode 100644

Just restore the missing execution permission using chmod +x myscript for that file in WSL.

You can also do a git checkout -- myfile from within WSL, to restore the permissions for that file by checking it out again, but note that this will also revert any other changes made to that file. git checkout -- . can be useful to restore the permissions on several files in the current directory and all subdirectories, but be aware that this command will revert ALL changes made to all files.

Use Windows Home Folder

In WSL, edit /etc/passwd and change your home folder:

carl-oskar:x:1000:1000:,,,:/c/Users/user.name:/bin/bash

Close all WSL sessions before restarting again.

Existing Files/Folders Permissions

If you already have ssh keys and configurations in $HOME/.ssh that were created in windows then you must change the file permission on those files to 600. Also fix $HOME/.gnupg if you are using GnuPG.

chmod -R 600 .ssh
chmod -R 600 .gnupg

Share Environment Variables from Windows to WSL

Windows environment variables are shared to WSL using a special environment variable called WSLENV that is a colon-delimited list of environment variables. WSLENV can also be used to share environment variables from WSL to Windows, useful when executing windows applications from WSL.

Each variable can be suffixed with a slash followed by flags to specify how it is translated, for example /up makes the variable available when invoking WSL from Win (p flag) with the path translated to WSL paths (u flag).

https://devblogs.microsoft.com/commandline/share-environment-vars-between-wsl-and-windows/

(Optional) /tmp in RAM

$ echo "tmpfs /tmp tmpfs rw,noatime,nosuid,nodev,size=1G" | sudo tee -a /etc/fstab

The above command will add an entry in fstab that will mount a temporary filesystem on /tmp which will use a maximum of 1 GB of RAM. Omitting size will use the default max which is half(?) the RAM.

GIT Setup

wslgit - the bridge between Windows and git in WSL

Download wslgit - fork-patch from here (follow the installation instructions!).

Speed up wslgit

By default wslgit executes most commands using non-interactive shell which does not execute .bashrc etc and therefore is fast.
But commands that access remotes are executed using interactive shell which do run .bashrc. If the .bashrc script contains a lot of initializations, like starting agents and other time consuming stuff then those commands can become slow.

The environment variable WSLGIT can be used to detect that .bashrc was started by wslgit, and if so only do a bare minimum of initialization, just so git can work properly, like starting ssh-agent etc.
If running .bashrc is not required then wslgit can be forced to always use non-interactive shell by, in Windows, define an environment variable named WSLGIT_USE_INTERACTIVE_SHELL and set it to false.

Using KDiff3 for diff and merge

  1. Add KDiff3 installation directory to the windows path so that WSL can find kdiff3.exe without the full path, makes the configuration prettier.
  2. Create a difftool config in .gitconfig for KDiff3, call it "kdiff3", whose command converts paths from unix-style to windows style, and configure it as diff.tool. Also configure KDiff3 as mergetool, which does not require any conversion of paths.
    [diff]
        guitool = kdiff3
    [difftool]
        prompt = false
    [difftool "kdiff3"]
        # Unix style paths must be converted to windows path style
        cmd = kdiff3.exe \"`wslpath -w $LOCAL`\" \"`wslpath -w $REMOTE`\"
        trustExitCode = false
    [merge]
        renormalize = true
        tool = kdiff3
    [mergetool]
        keepBackup = false
        prompt = false
        path = kdiff3.exe
        trustExitCode = false

VSCode Setup

Using git from WSL in VSCode

If you put wslgit in a folder on your PATH (and named it git.exe) then VSCode just picks it up.

If not, to make VSCode use it add the path to wslgit.exe in VSCode settings:

{
    "git.path": "C:\\path\\to\\wslgit.exe",
}

Use wsltty as External Terminal and WSL as Integrated Terminal

Add the path to WSL.bat in wsltty in VSCode settings:

{
    "terminal.explorerKind": "external",
    "terminal.external.windowsExec": "C:\\Users\\user.name\\AppData\\Local\\wsltty\\WSL.bat",
    "terminal.integrated.shell.windows": "C:\\WINDOWS\\System32\\wsl.exe",
}
@carlolars

This comment has been minimized.

Copy link
Owner Author

@carlolars carlolars commented Oct 9, 2019

The kdiff3 integration is even easier when using wslpath, and there is no need to share TMP since the windows side now has access to the entire WSL filesystem via \wsl$.

@carlolars

This comment has been minimized.

Copy link
Owner Author

@carlolars carlolars commented Oct 9, 2019

Moved wslgit instructions from VSCode section to first in Git Setup

@HankAviator

This comment has been minimized.

Copy link

@HankAviator HankAviator commented Sep 27, 2020

I only managed to get kdiff3 to work as a mergetool by using this line:

cmd = '/mnt/c/Program Files/KDiff3/kdiff3.exe' \"`wslpath -w $BASE`\" \"`wslpath -w $LOCAL`\" \"`wslpath -w $REMOTE`\" --output \"`wslpath -w $MERGED`\"
@carlolars

This comment has been minimized.

Copy link
Owner Author

@carlolars carlolars commented Oct 7, 2020

I only managed to get kdiff3 to work as a mergetool by using this line:

cmd = '/mnt/c/Program Files/KDiff3/kdiff3.exe' \"`wslpath -w $BASE`\" \"`wslpath -w $LOCAL`\" \"`wslpath -w $REMOTE`\" --output \"`wslpath -w $MERGED`\"

I did some testing and for WSL2 it appears that the custom difftool.kdiff3.cmd is not needed anymore 👍 .
For WSL1 I still have to use the custom difftool.kdiff3.cmd but I don't need a custom mergetool.kdiff3.cmd.

Which WSL version are you using?
And what version of KDiff3? I'm using the really old kdiff3 Version 0.9.98 (64 bit). There is a newer version maintained by KDE which is not working at all for me.

@HankAviator

This comment has been minimized.

Copy link

@HankAviator HankAviator commented Oct 9, 2020

Argh, I just noticed last night that git will copy files to /tmp sometimes when I run git difftool, and my kdiff3 doesn't recognize UNC at all!
Version for my kdiff3 is 1.8.4, 64 bit. I run WSL2 too.
Think I'll give meld a try :<

@HankAviator

This comment has been minimized.

Copy link

@HankAviator HankAviator commented Nov 11, 2020

Meld works much better than kdiff3, just slow launch and somehow sluggish compared to kdiff3 but at least UNC is fundamental in WSL2 development :/

@Ridder90

This comment has been minimized.

Copy link

@Ridder90 Ridder90 commented Jan 22, 2021

After applying the meta I cannot start docker-compose.exe and explorer.exe anymore because of the permission denied. Unfortunatly i cannot add the execution permission.

sudo chmod 775 '/mnt/c/Program Files/Docker/Docker/resources/bin/docker-credential-desktop.exe'
[sudo] password for florian:
chmod: changing permissions of '/mnt/c/Program Files/Docker/Docker/resources/bin/docker-credential-desktop.exe': Permission denied

Even while i am the owner of those files :S Any ideas?

EDIT: actually it seem to work by also adding the root=/ . Not sure why though 🤔

@carlolars

This comment has been minimized.

Copy link
Owner Author

@carlolars carlolars commented Jan 23, 2021

Even while i am the owner of those files :S Any ideas?

You must start the WSL2 terminal as administrator (Run as administrator) to be allowed to chmod files in Windows or any of the two Program Files folders. No need for sudo then since it is a Windows permission issue and not on the Linux side.

@Ridder90

This comment has been minimized.

Copy link

@Ridder90 Ridder90 commented Jan 25, 2021

Thanks for your help! I opened wsl with Run as administrator, but unfortunately still cannot change the permissions.

florian@T490-WIN:/c/WINDOWS/system32$ chmod +x cmd.exe                                                                                                  
chmod: changing permissions of 'cmd.exe': Permission denied                                                                                             
florian@T490-WIN:/c/WINDOWS/system32$ sudo chmod +x cmd.exe                                                                                             
[sudo] password for florian:                                                                                                                            
chmod: changing permissions of 'cmd.exe': Permission denied         

I will do my own research. But any help is very much appreciated :)

@carlolars

This comment has been minimized.

Copy link
Owner Author

@carlolars carlolars commented Jan 25, 2021

@Ridder90 It appears that I actually cannot change permissions on anything in C:\Windows, but C:\Program Files works, for example docker-credential-desktop.exe.
The strange thing is that I must have been successful at some time because C:\Windows\write.exe has execute permissions.

@HankAviator

This comment has been minimized.

Copy link

@HankAviator HankAviator commented Mar 11, 2021

Carl why do you need to do this instead of invoking git.exe offered in Windows git release instead?

@carlolars

This comment has been minimized.

Copy link
Owner Author

@carlolars carlolars commented Mar 12, 2021

@HankAviator Windows git doesn't honor the mode bits for a file, which cause problems if checking out with windows-git and then work on the files in WSL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment