Qual é a melhor estratégia de manuseio de CRLF (retorno de carro, avanço de linha) com o Git?

Eu tentei confirmar arquivos com linhas que terminam com o CRLF, mas ele falhou.

Passei um dia inteiro de trabalho no meu computador com Windows experimentando estratégias diferentes e estava quase tentando parar de tentar usar o Git e, em vez disso, experimentar o Mercurial .

Por favor, compartilhe apenas uma das melhores práticas por resposta.

Quase quatro anos depois de fazer essa pergunta, finalmente encontrei uma resposta que me satisfaz completamente !

Veja os detalhes no github: guia de ajuda para lidar com finais de linha .

O Git permite que você defina as propriedades finais da linha para um repo diretamente usando o atributo text no arquivo .gitattributes . Este arquivo é confirmado no core.autocrlf e substitui a configuração core.autocrlf , permitindo que você garanta um comportamento consistente para todos os usuários, independentemente de suas configurações de git.

E assim

A vantagem disso é que sua configuração de fim de linha agora viaja com seu repository e você não precisa se preocupar se os colaboradores têm ou não as configurações globais adequadas.

Aqui está um exemplo de um arquivo .gitattributes

 # Auto detect text files and perform LF normalization * text=auto *.cs text diff=csharp *.java text diff=java *.html text diff=html *.css text *.js text *.sql text *.csproj text merge=union *.sln text merge=union eol=crlf *.docx diff=astextplain *.DOCX diff=astextplain # absolute paths are ok, as are globs /**/postinst* text eol=lf # paths that don't start with / are treated relative to the .gitattributes folder relative/path/*.txt text eol=lf 

Existe uma coleção conveniente de arquivos .gitattributes prontos para uso para as linguagens de programação mais populares. É útil para você começar.

Depois de criar ou ajustar seus .gitattributes , você deve executar uma nova normalização de .gitattributes uma vez por todas.

Observe que o aplicativo GitHub Desktop pode sugerir e criar um arquivo .gitattributes depois que você abrir o .gitattributes Git do seu projeto no aplicativo. Para tentar isso, clique no ícone de engrenagem (no canto superior direito)> Configurações do repository …> Endings e atributos de linha. Você será solicitado a adicionar os .gitattributes recomendados .gitattributes e se você concordar, o aplicativo também executará uma normalização de todos os arquivos em seu repository.

Finalmente, o artigo Mind the End of Your Line fornece mais informações e explica como o Git evoluiu nos assuntos em questão. Eu considero essa leitura obrigatória .

Você provavelmente tem usuários em sua equipe que usam EGit ou JGit (ferramentas como Eclipse e TeamCity os usam) para confirmar suas mudanças. Então você está sem sorte, como @gatinueta explicou nos comentários desta resposta:

Esta configuração não irá satisfazê-lo completamente se você tem pessoas trabalhando com Egit ou JGit em sua equipe, uma vez que essas ferramentas irão simplesmente ignorar .gitattributes e felizmente verificar em arquivos CRLF https://bugs.eclipse.org/bugs/show_bug.cgi? id = 342372

Um truque pode ser que eles cometam suas alterações em outro cliente, digamos, SourceTree . Nossa equipe preferiu essa ferramenta ao EGit do Eclipse para muitos casos de uso.

Quem disse que o software é fácil? : – /

Não converta finais de linha. Não é tarefa do VCS interpretar dados – basta armazená-los e modificá-los. Todo editor de texto moderno pode ler os dois tipos de finalização de linha.

Você quase sempre quer autocrlf=input menos que você realmente saiba o que está fazendo.

Algum contexto adicional abaixo:

Deve ser core.autocrlf=true se você gosta do DOS terminando ou core.autocrlf=input se você preferir unix-newlines. Em ambos os casos, seu repository Git terá apenas LF, que é a coisa certa. O único argumento para core.autocrlf=false foi que a heurística automática pode detectar incorretamente algum binário como texto e, em seguida, seu bloco será corrompido. Então, a opção core.safecrlf foi introduzida para avisar um usuário se uma mudança irreversível acontece. De fato, existem duas possibilidades de mudanças irreversíveis – finalização de linha mista no arquivo de texto, nesta normalização é desejável, portanto este aviso pode ser ignorado, ou (muito improvável) que o Git detectou incorretamente seu arquivo binário como texto. Então você precisa usar atributos para dizer ao Git que este arquivo é binário.

O parágrafo acima foi originalmente extraído de um tópico no gmane.org, mas desde então ele foi desativado.

Duas estratégias alternativas para obter consistência sobre fins de linha em ambientes mistos (Microsoft + Linux + Mac):

A. Configuração Global de Todos os Repositórios

1) Converta todos para um formato

 find . -type f -not -path "./.git/*" -exec dos2unix {} \; git commit -a -m 'dos2unix conversion' 

2) Defina core.autocrlf como input no Linux / UNIX ou true no MS Windowns (repository ou global)

 git config --global core.autocrlf input 

3) [Opcional] defina core.safecrlf como true (para parar) ou warn (para cantar 🙂 para adicionar guarda extra, comparando se a transformação de nova linha invertida resultaria no mesmo arquivo

 git config --global core.safecrlf true 

B. Ou por Configuração de Repositório

1) Converta todos para um formato

 find . -type f -not -path "./.git/*" -exec dos2unix {} \; git commit -a -m 'dos2unix conversion' 

2) adicione o arquivo .gitattributes ao seu repository

 echo "* text=auto" > .gitattributes git add .gitattributes git commit -m 'adding .gitattributes for unified line-ending' 

Não se preocupe com seus arquivos binários – o Git deve ser inteligente o suficiente sobre eles.


Mais sobre as variables ​​safecrlf / autocrlf

Tente definir a opção de configuração core.autocrlf como true . Também dê uma olhada na opção core.safecrlf .

Na verdade, parece que o core.safecrlf pode já estar no seu repository, porque (ênfase minha):

Se este não for o caso da configuração atual de core.autocrlf, o git rejeitará o arquivo .

Se este for o caso, você pode querer verificar se o seu editor de texto está configurado para usar terminações de linha consistentemente. Você provavelmente terá problemas se um arquivo de texto contiver uma mistura de terminações de linha LF e CRLF.

Finalmente, sinto que a recomendação de simplesmente “usar o que você recebeu” e usar linhas terminadas em LF no Windows causará mais problemas do que resolve. O Git tem as opções acima para tentar lidar com finais de linha de uma maneira sensata, então faz sentido usá-los.

Usando core.autocrlf=false impediu que todos os arquivos fossem marcados como atualizados assim que eu os registrasse em meu projeto do Visual Studio 2010 . Os outros dois membros da equipe de desenvolvimento também estão usando sistemas Windows para que um ambiente misto não entre em jogo, mas as configurações padrão que vieram com o repository sempre marcaram todos os arquivos como atualizados imediatamente após a clonagem.

Eu acho que a linha de fundo é encontrar o que a configuração CRLF funciona para o seu ambiente. Especialmente desde que em muitos outros repositorys em nossas checkboxs Linux a configuração autocrlf = true produz melhores resultados.

20 + anos mais tarde e ainda estamos lidando com disparidades de terminação de linha entre sistemas operacionais … triste.

Essas são as duas opções para usuários do Windows e do Visual Studio que compartilham código com usuários de Mac ou Linux . Para uma explicação mais detalhada, leia o manual gitattributes .

* text = auto

No arquivo .gitattributes do repo, adicione:

 * text=auto 

Isso normalizará todos os arquivos com terminações de linha LF no repo.

E, dependendo do seu sistema operacional (configuração core.eol ), os arquivos na tree de trabalho serão normalizados para LF para sistemas baseados em Unix ou CRLF para sistemas Windows.

Esta é a configuração que os repositorys Microsoft .NET usam.

Exemplo:

 Hello\r\nWorld 

Será normalizado no repo sempre como:

 Hello\nWorld 

No check-out, a tree de trabalho no Windows será convertida em:

 Hello\r\nWorld 

No checkout, a tree de trabalho no Mac será deixada como:

 Hello\nWorld 

Nota: Se o seu repo já contiver arquivos não normalizados, o git status mostrará esses arquivos como completamente modificados na próxima vez que você fizer alguma alteração neles, e pode ser difícil para outros usuários mesclarem suas alterações posteriormente. Consulte a atualização de um repository depois de alterar os finais de linha para obter mais informações.

core.autocrlf = true

Se o text não for especificado no arquivo .gitattributes , o Git usará a variável de configuração core.autocrlf para determinar se o arquivo deve ser convertido.

Para usuários do Windows, git config --global core.autocrlf true é uma ótima opção porque:

  • Os arquivos são normalizados apenas para finais de linha LF quando adicionados ao repository. Se houver arquivos não normalizados no repository, essa configuração não os tocará.
  • Todos os arquivos de texto são convertidos em finais de linha CRLF no diretório de trabalho.

O problema com essa abordagem é que:

  • Se você é um usuário do Windows com autocrlf = input , você verá um monte de arquivos com terminações de linha LF . Não é um risco para o resto da equipe, porque seus commits ainda serão normalizados com finais de linha LF .
  • Se você é um usuário do Windows com core.autocrlf = false , você verá um monte de arquivos com terminações de linha LF e poderá introduzir arquivos com terminações de linha CRLF no repo.
  • A maioria dos usuários de Mac usa autocrlf = input e pode obter arquivos com terminações de arquivos CRLF , provavelmente de usuários do Windows com core.autocrlf = false .

Esta é apenas uma solução alternativa :

Em casos normais, use as soluções fornecidas com o git. Estes funcionam muito bem na maioria dos casos. Força para LF se você compartilhar o desenvolvimento em sistemas baseados em Windows e Unix, definindo .gitattributes .

No meu caso, havia mais de 10 programadores desenvolvendo um projeto no Windows. Este projeto foi verificado com CRLF e não houve opção para forçar a LF.

Algumas configurações foram escritas internamente na minha máquina, sem qualquer influência no formato LF; Assim, alguns arquivos foram alterados globalmente para LF em cada pequena alteração de arquivo.

Minha solução:

Windows-Machines: deixe tudo como está. Preocupe-se com nada, já que você é um desenvolvedor padrão de ‘lobo solitário’ do Windows e precisa lidar assim: “Não existe outro sistema no mundo inteiro, não é?”

Unix-Machines

  1. Adicione as seguintes linhas à seção [alias] configuração. Este comando lista todos os arquivos alterados (ou seja, modificados / novos):

     lc = "!f() { git status --porcelain \ | egrep -r \"^(\?| ).\*\\(.[a-zA-Z])*\" \ | cut -c 4- ; }; f " 
  2. Converta todos os arquivos alterados em formato DOS:

     unix2dos $(git lc) 
  3. Opcionalmente …

    1. Crie um gancho git para esta ação para automatizar este processo

    2. Use params e inclua-o e modifique a function grep para corresponder apenas a nomes de arquivos específicos, por exemplo:

       ... | egrep -r "^(\?| ).*\.(txt|conf)" | ... 
    3. Sinta-se à vontade para torná-lo ainda mais conveniente usando um atalho adicional:

       c2dos = "!f() { unix2dos $(git lc) ; }; f " 

      … e triggersr o material convertido digitando

       git c2dos 

Passei horas para encontrar o melhor uso possível de .gitattributes de .gitattributes , para finalmente perceber que não posso contar com isso.
Infelizmente, enquanto existirem editores baseados em JGit (que não podem manipular corretamente os .gitattributes ), a solução segura é forçar o LF em qualquer lugar, mesmo em nível de editor.

Use os seguintes desinfetantes anti-CRLF .

— Atualização —

Mesmo se você não quiser usar a estratégia acima, o seguinte comando é seu amigo ( Nota: no windows clients funciona somente através de git-bash e em clientes linux somente se compilado usando --with-libpcre em ./configure ).

 # Print all files that have been committed with CRLF (more correctly that contain CR), so that you normalize them. git grep -I --files-with-matches --perl-regexp '\r' HEAD 

Um exemplo doloroso :

O netbeans 8.2 (no windows), irá erroneamente confirmar todos os arquivos de texto com CRLFs no repository , a menos que você tenha definido explicitamente core.autocrlf como global . Isso contradiz o comportamento padrão do cliente git e causa muitos problemas mais tarde, durante a atualização / mesclagem. Isso é o que faz com que alguns arquivos pareçam diferentes (embora não sejam), mesmo quando você reverte .
O mesmo comportamento no netbeans acontece mesmo se você tiver adicionado .gitattributes corretos ao seu projeto.

Usar o comando acima após um commit, pelo menos, ajudará você a detectar antecipadamente se o seu repository git tem problemas de finalização de linha.