Por que devo usar core.autocrlf = true no Git?

296

Eu tenho um repositório Git que é acessado no Windows e no OS X e que eu sei que já contém alguns arquivos com finais de linha CRLF. Até onde eu sei, existem duas maneiras de lidar com isso:

  1. Defina core.autocrlfpara falsequalquer lugar,

  2. Siga as instruções aqui (ecoadas nas páginas de ajuda do GitHub) para converter o repositório para conter apenas terminações de linhas LF e, posteriormente, definido core.autocrlfcomo trueno Windows e inputno OS X. O problema é que se eu tiver arquivos binários no repositório aquele:

    1. não estão corretamente marcados como binários em gitattributes e
    2. por acaso contenham CRLFs e LFs,

    eles serão corrompidos. É possível que meu repositório contenha esses arquivos.

Então, por que eu não deveria simplesmente desativar a conversão de final de linha do Git? Há uma série de advertências vagas na web sobre ter core.autocrlfdesligado causando problemas, mas muito poucos específicos queridos; o único que descobri até agora é que o kdiff3 não pode lidar com terminações CRLF (não é um problema para mim) e que alguns editores de texto têm problemas de final de linha (também não são um problema para mim).

O repositório é interno à minha empresa e, portanto, não preciso me preocupar em compartilhá-lo com pessoas com diferentes configurações de autocrlf ou requisitos de final de linha.

Existem outros problemas em deixar os finais de linha como eu desconheço?

Rico
fonte
1
Seria stackoverflow.com/questions/2333424/... ajuda? Eu tenho um link para razões específicas para deixar autocrlfpara false.
VonC
3
@VonC Obrigado, mas já sou capaz de ditar que todos os usuários da empresa definam <code> autocrlf </code> como false e atualmente acreditem que essa seja a melhor opção. Mas quero saber se há alguma razão pela qual não devo fazer isso, porque posso encontrar muitas pessoas (por exemplo, GitHub) que dizem que o autocrlf deve ser definido, mas não há detalhes específicos sobre o porquê.
Rich
3
@VonC, ou seja, não estou procurando motivos para definir autocrlfcomo falso. Estou procurando por razões para defini-lo como verdadeiro.
Rich
9
Por que não usar autocrlf = input: parece ser a resolução perfeita entre os dois extremos: você mantém seu repositório limpo de porcarias de CRLF, e os desenvolvedores localmente do Windows podem usar o que quiserem sem que seus arquivos locais tenham algo mágico feito automaticamente. (Eles podem querer LF localmente por vários motivos, truena minha opinião , isso é ruim.) Não vejo desvantagens no uso autocrlf = input.
iconoclast
7
@iconclast, um dos motivos pelos quais me deparei é se você criar distribuições que incluem arquivos em lote do Windows e scripts de shell do Unix. Você deseja usar a linha correta que termina em cada caso, e isso é mais difícil se o Git estiver mexendo nas coisas, mesmo depois que você as definir explicitamente de uma maneira ou de outra.
user1809090

Respostas:

227

As razões única específicos para definir autocrlfa truesão:

  • evite git statusmostrar todos os seus arquivos modifieddevido à conversão automática de EOL ao clonar um repositório EOL Git baseado em Unix para um repositório do Windows (consulte o problema 83, por exemplo)
  • e suas ferramentas de codificação dependem de algum modo de um estilo EOL nativo presente no seu arquivo:

A menos que você possa ver um tratamento específico que deve lidar com a EOL nativa, é melhor sair autocrlfparafalse ( git config --global core.autocrlf false).

Observe que essa configuração seria local (porque a configuração não é enviada de um repositório para outro)

Se você quer a mesma configuração para todos os usuários de clonagem que repo, confira " Qual é a melhor CRLFestratégia de tratamento com git? ", Usando o textatributo no .gitattributesarquivo .

Exemplo:

*.vcproj    text eol=crlf
*.sh        text eol=lf

Nota: a partir do git 2.8 (março de 2016), os marcadores de mesclagem não introduzirão mais o final de linha mista (LF) em um arquivo CRLF.
Consulte " Faça o Git usar CRLF em suas linhas de mesclagem" <<<<<<< HEAD "

VonC
fonte
5
@VonC Thanks! Isso me ajuda a me sentir mais confiante de que é seguro usar autocrlf=false. Por interesse, você sabe por que o git ainda faz a conversão de eol, mesmo se o autocrlf estiver definido como false?
Rich
14
@VonC: Eu não acho que esta resposta esteja correta. O uso de core.autocrlf = true no Windows funciona conforme o esperado. Todos os arquivos do repositório (que devem ter finais de linha LF neste cenário) são convertidos em finais de linha CRLF no checkout para um PC com Windows. Todos os arquivos são convertidos novamente nas terminações da linha LF na confirmação a partir de um PC com Windows. A maneira de entrar em problemas é fazer o check-out inicialmente em um PC com Windows com a configuração core.autocrlf errada (que é muito fácil de fazer).
Michael Maddox
3
@ Michael Então, nesse caso, a única razão para não usar core.autocrlf=falseno meu cenário é se eu tivesse alguma ferramenta / editor que ficaria confuso com os finais de linha?
Ricos
49
Eu definitivamente usaria false, nunca fui um grande fã de coisas automáticas ou mágicas acontecendo em segundo plano. Basta usar \ne em UTF-8qualquer lugar e você ficará bem. Se algum maluco não entender que existem convenções, regras e esquecimentos para usar UTF-8ou \n, então alguém os converte manualmente e dá um tapa no rosto.
Torre
5
@ Pauld'Aoust Eu ainda preferiria especificar o tipo de arquivo que precisa desse CRLF por meio de core.eolatributos em um .gitattributesarquivo, em vez de usar essa core.autocrlfconfiguração global que se aplica indiscriminadamente a todos os arquivos.
VonC
40

Sou desenvolvedor .NET e uso o Git e o Visual Studio há anos. Minha forte recomendação é definir finais de linha como true. E faça isso o mais cedo possível durante a vida útil do seu Repositório.

Dito isto, eu odeio que o Git mude meus finais de linha. Um controle de origem deve salvar e recuperar apenas o trabalho que eu faço, NÃO deve modificá-lo. Sempre. Mas sim.

O que acontecerá se você não tiver todos os desenvolvedores definidos como verdadeiros, é UM desenvolvedor eventualmente definido como verdadeiro. Isso começará a alterar as terminações de linha de todos os seus arquivos para LF no seu repositório. E quando os usuários configurados como falsos, verificá-los, o Visual Studio avisa e solicita que você os altere. Você terá duas coisas que acontecem muito rapidamente. Primeiro, você receberá mais e mais desses avisos, quanto maior sua equipe, mais você recebe. A segunda coisa, e pior, é que ela mostrará que todas as linhas de todos os arquivos modificados foram alteradas (porque as terminações de cada linha serão alteradas pelo cara verdadeiro). Eventualmente, você não poderá mais acompanhar as alterações em seu repo. É MUITO mais fácil e limpo fazer com que todos se mantenham verdadeiros do que tentar manter todos falsos. Por mais horrível que seja viver com o fato de que seu controle de fonte confiável está fazendo algo que não deveria. Sempre.

JGTaylor
fonte
Minha empresa é pequena o suficiente para que possamos facilmente ordenar que false seja usado em todos os lugares, e eu pensaria que empresas maiores poderiam fazer isso via política, mas acho que esse é um motivo legítimo para usar "true", por isso estou votando de qualquer forma. Obrigado!
Ricos
1
O problema de fazer isso com uma política (arquivo imposto) é que, em uma máquina Windows, é possível ter um arquivo de configuração local, global e oculto (ProgramData / Git / Confg). Você pode impor o local, verificando-o no repositório, mas os arquivos Global AND e ocultos têm precedência. Também é possível ter local e global (ou oculto) ser diferente. Se estiverem, entrarão em conflito entre si na mesma máquina, causando erros de final de linha onde não há nenhum. É uma dor para rastrear. :(
JGTaylor
7
exatamente o que eu penso. não é o trabalho de um controle de origem mexer com arquivos de código como quiser. terminações de linha devem ser simplesmente uma preocupação das ferramentas de edição, nada mais.
Tuncay Göncüoğlu 18/08/16
6
Se o seu projeto é somente para Windows, não há problema. No entanto, se você ou seus colegas trabalharem em uma plataforma * nix, sua "forte recomendação" causará problemas. Tente executar um script bash, perl ou python com o shebang terminado com \r\ne você verá.
Phuclv
6
A situação que você descreveu como não é problema do GIT, defina a configuração como FALSE como normalmente deveria ser e ela desapareceu. Instad, é um problema no trabalho em equipe. O que significa "eventualmente um desenvolvedor define true"? Por que você permitiria isso em primeiro lugar? quando você os configura para acessar o repositório git, assim como você não permite poluir determinadas áreas com diferentes idiomas (para que qualquer pessoa que trabalhe nele possa lê-lo), ou apenas como você mantém ramos / mesclagens / rebotes / etc ao longo do escolhido política, eles devem ter uma regra clara: defina o crlf correto.
quetzalcoatl
12

Atualização 2 :

O Xcode 9 parece ter um "recurso" onde ele ignora as terminações de linha atuais do arquivo e, em vez disso, apenas usa sua configuração de final de linha padrão ao inserir linhas em um arquivo, resultando em arquivos com finais de linha mistos.

Tenho certeza de que esse bug não existia no Xcode 7; não tenho certeza sobre o Xcode 8. A boa notícia é que ele parece estar corrigido no Xcode 10.

Durante o tempo em que ele existiu, esse bug causou uma pequena quantidade de hilaridade na base de código a que me refiro na pergunta (usada até hoje autocrlf=false) e levou a muitas mensagens de confirmação de "EOL" e, eventualmente, à minha escrita de um pre-commitgancho git para verificar para / impedir a introdução de terminações de linhas mistas.

Atualização :

Nota: Como observado por VonC, a partir Git 2.8, marcadores de mesclagem irá não apresentar Unix de estilo linha-finais em um arquivo de estilo do Windows .

Original :

Um pequeno problema que eu notei nessa configuração é que, quando há conflitos de mesclagem, as linhas que o git adiciona para marcar as diferenças não têm finais de linha do Windows, mesmo quando o restante do arquivo possui, e você pode acabar com um arquivo com finais de linha mistos, por exemplo:

// Some code<CR><LF>
<<<<<<< Updated upstream<LF>
// Change A<CR><LF>
=======<LF>
// Change B<CR><LF>
>>>>>>> Stashed changes<LF>
// More code<CR><LF>

Isso não nos causa problemas (imagino que qualquer ferramenta que possa lidar com os dois tipos de final de linha também lida com final de linha misto - certamente todos os que usamos) -, mas é algo para estar ciente.

A outra coisa * que descobrimos é que, ao usar git diffpara exibir alterações em um arquivo com finais de linha do Windows, as linhas adicionadas exibem seus retornos de carro, assim:

    // Not changed

+   // New line added in^M
+^M
    // Not changed
    // Not changed

* Ele realmente não merece o termo: "questão".

Rico
fonte
2
NB Quando o Visual Studio encontra esse arquivo, ele oferece a normalização das terminações de linha para você. Escolher finais de linha do Windows ou optar por não normalizar os finais de linha funciona bem (como o VS ainda o exibe corretamente, as linhas incorretas serão excluídas após a resolução do conflito).
Rich
2
Infelizmente, os nazistas de controle de versão corporativo discordam dele (LF em marcadores de conflito de mesclagem) não sendo um problema.
Ilia G
1
Concordo que a LF em mesclar marcadores de conflito não deve ser um problema. Essas linhas não devem ser comprometidas com o repo de qualquer maneira.
rob
1
Nota: a partir do git 2.8 (março de 2016), os marcadores de mesclagem terão realmente o final da linha CRLF. Veja stackoverflow.com/a/35474954/6309
VonC