Git on Windows

Switching my development hardware to Windows brought some problems when working with git - using the very same git repository. They probably were caused by the mixed use of powershell, git bash, cygwin, WSL (Windows Subsystem for Linux), and even Visual Studio.

Problems

Two problems really frustrated me:

Bogus file changes would show up, which I could not resolve at all. I tried

in any case, the file still showed up as modified in git status :-(. This also means no rebase can be done (“modifications, please stash”) and nothing can be checked out that would overwrite those changed files.

At other times git status would show that all files are modified. Then git diff would show the whole file as modified. Which made it impossible to find out what actually changed, e.g. when preparing a commit.

Solutions

The latter problem (all files modified) was more obvious: The repository contains Linux-style line endings (“lf”: line feed), while the working directory contains Windows-style line endings (“crlf”: carriage-return and line feed).

This blog post contained the solution:

git config --global core.autocrlf input

git config --global core.eol lf

When you checkout a commit, git will convert the line endings according to the latter variable. When not set, the default is “native”, which means the files will be converted to lf on Linux and clrf on Windows. My guess is, that this becomes problematic when using WSL’s git in the same directory as the git installed in Windows’. One will expect lf and the other crlf.

The second option overwrites the behavior of core.eol (probably one of the options is enough). “input” means: Do not convert (here the input are the files from the repository).

From the git docs

core.autocrlf

Setting this variable to “true” is the same as setting the text attribute to “auto” on all files and core.eol to “crlf”. Set to true if you want to have CRLF line endings in your working directory and the repository has LF line endings. This variable can be set to input, in which case no output conversion is performed.

core.eol

Sets the line ending type to use in the working directory for files that are marked as text (either by having the text attribute set, or by having text=auto and Git auto-detecting the contents as text). Alternatives are lf, crlf and native, which uses the platform’s native line ending. The default value is native. See gitattributes[5] for more information on end-of-line conversion. Note that this value is ignored if core.autocrlf is set to true or input.

The harder problem were the bogus file changes. I write “bogus”, because the files weren’t changed. As stated above, even delting the file and checking it out again would not work to reset its status to unchanged.

At some point I noticed git saying something about the mode (i.e. the access permissions) of the file. I found a solution on this page:

git config core.filemode false

which tells git to ignore those changes - that’s it, everything works now.

Related section from the git docs (emphasis mine):

core.fileMode

Tells Git if the executable bit of files in the working tree is to be honored.

Some filesystems lose the executable bit when a file that is marked as executable is checked out, or checks out a non-executable file with executable bit on. git-clone[1] or git-init[1] probe the filesystem to see if it handles the executable bit correctly and this variable is automatically set as necessary.

A repository, however, may be on a filesystem that handles the filemode correctly, and this variable is set to true when created, but later may be made accessible from another environment that loses the filemode (e.g. exporting ext4 via CIFS mount, visiting a Cygwin created repository with Git for Windows or Eclipse). In such a case it may be necessary to set this variable to false. See git-update-index[1].

The default is true (when core.filemode is not specified in the config file).



Home