Peguei algo interessante hoje, sem querer. Estou começando a usar o Bash do Windows Subsystem for Linux (WSL) como um dos meus ambientes de linha de comando principais. Isso quer dizer fazer os commits do Git em um ambiente Linux, mesmo quando usando Windows. Apenas lembrando rapidamente, o WSL roda o user mode do Linux, com binários ELF não modificados, enquanto o kernel mode é emulado pelo kernel do Windows através de uma leve camada intermediária. Sim, o kernel do Windows é poderoso o suficiente para emular o kernel do Linux. Não vou entrar em detalhes, mas o que está acontecendo é uma série de implementações de syscalls do kernel do Linux, no Windows, entre outras abstrações diversas (inodes, namespaces, etc).

É lindo, a diferença de file system é compreendida, e tudo funciona. Mas há um detalhe: o Git, hoje em dia, entende o sistema operacional em que está rodando, e vai utilizar as configurações de final de linha (end of line) de acordo com o SO. Essas configs eram um problema uns anos atrás, e já causaram muita dor de cabeça, mas hoje em dia essa é questão é um problema resolvido. Não sei exatamente quando isso foi resolvido, mas validei que no Linux hoje em dia os line endings são resolvidos no working directory de maneira diferente no Windows e Linux, independentemente de configuração. No Windows o checkout padrão é CRLF, e no Linux é LF (como deveria ser). Você pode ler mais sobre esse problema, quando ele existia, neste artigo do Github.

No entanto, um problema surge quando você usa 2 sistemas operacionais sobre o mesmo sistema de arquivos, e é exatamente isso que acontece no caso do WSL. Por exemplo, para um projeto de .NET, o checkout padrão acontece no Windows, os arquivos são usados no Windows, com CRLF. No entanto, ao tentar fazer o commit pelo WSL, onde o Git entende estar em outro sistema operacional, você terá um problema.

Veja abaixo o que acontece ao alterar alguns arquivo no Windows, e pedir um git status no Linux (WSL) – clique para ampliar a imagem:

git diff mostrando warnings de CRLF

git diff mostrando warnings de CRLF

Para resolver, basta setar a config do repositório como CRLF true:

git config core.autocrlf true

O comando deve ser dado de dentro do diretório, para que as alterações fiquem guardadas no repo. Para vê-las basta rodar um git config -e, ou exibir o arquivo config dentro de .git:

cat .git/config

Você verá o valor setado (entro outros, limitado para exibição):

[core]
  autocrlf = true

Ao fazer o commit agora, o warning não vai aparecer.

Happy gitting.