Desativar conversões git EOL

100

Estou tentando fazer com que o git não mude quaisquer terminações de linha para qualquer operação. Infelizmente, parece que não importa o quê. Eu o reduzi ao seguinte caso de teste, que tem tantos mecanismos diferentes para desativar esse comportamento quanto pude encontrar.


  • Comece com duas máquinas (computador Windows = A, computador Linux = B)
  • Em ambas as máquinas: git config --global core.autocrlf false
  • Em ambas as máquinas: git config --global core.eol crlf(apenas no caso)

  • Faça um novo repositório em A. De uma pasta vazia:
    • git init --shared(em seguida, reexibir o .gitdiretório criado )
    • Faça um novo arquivo .gitignoreno repositório
    • Faça um novo arquivo .gitattributesno repositório com a única linha:* -text
    • git add ., então git commit -m "initial commit"para contornar, por exemplo, isso .
    • git branch master_recv
    • Adicionar controles remotos
  • Faça um novo arquivo document.txtno repositório contendo CRLF
  • Commit:, git add -Aentãogit commit -m "<something>"
  • Observe que A's document.txtainda contém CRLF (e excluí-lo e redefinir com --hardretorna a versão ainda com CRLF)

  • SCP todo o diretório para o computador B
  • Adicionar um novo arquivo new filecontendo CRLF
  • Commit:, git add -Aentãogit commit -m "<something>"
  • Observe que B's document.txte B's new fileainda contêm CRLF

  • Puxe o mestre de B para A: git pull <remote> master:master_recv
  • A's document.txtmudou para LF. O arquivo adicionado new filetambém contém LF.

O problema não ocorre se B for uma máquina Windows.

Imallett
fonte
Tem core.autocrlf sempre sido falso? Parece que você já tem \nterminações de linha em seu repositório? Não configuração para alterar \nem seu repositório \r\nem seu diretório de trabalho.
Edward Thomson
Nem sempre foi definido (por exemplo, quando o repo foi criado originalmente). No entanto, não deve haver quaisquer terminações de linha CR no repo já. Além disso, novamente, não quero que nenhuma mudança aconteça.
imallett
Eu pergunto porque sua configuração deve preservar as terminações de linha como CRLF. Você poderia postar algum arquivo em seu repositório com seu ID de objeto apenas para minha edificação (reconhecidamente provavelmente irritante)?
Edward Thomson
@EdwardThomson como assim? O repo não é público (já que a máquina Linux não é). Presumo que você queira um arquivo de exemplo. Veja editar.
imallett
Sim, concordo que esse arquivo tem terminações de linha CRLF. Você pode esclarecer uma coisa: você mencionou que as "novas linhas da máquina Windows mudam para CR!" Certamente isso foi um erro de digitação ou você está realmente recebendo terminações de linha de retorno de carro no estilo Mac OS 9?
Edward Thomson

Respostas:

74

Dentro do seu projeto, deve haver um .gitattributesarquivo. Na maioria das vezes, a aparência deve ser a seguinte (ou esta captura de tela ):

# Handle line endings automatically for files detected as text 
# and leave all files detected as binary untouched.
* text=auto

# Never modify line endings of our bash scripts
*.sh -crlf

#
# The above will handle all files NOT found below
#
# These files are text and should be normalized (Convert crlf => lf)
*.css           text
*.html          text
*.java          text
*.js            text
*.json          text
*.properties    text
*.txt           text
*.xml           text

# These files are binary and should be left untouched
# (binary is macro for -text -diff)
*.class         binary
*.jar           binary
*.gif           binary
*.jpg           binary
*.png           binary

Mude * text=autopara * text=falsepara desativar o manuseio automático (veja a captura de tela ).

Como isso:

insira a descrição da imagem aqui

Se seu projeto não tem um arquivo .gitattributes, então as terminações de linha são definidas por suas configurações git. Para alterar suas configurações git, faça o seguinte:

Vá para o arquivo de configuração neste diretório:

1) C: \ ProgramData \ Git \ config

2) Abra o arquivo de configuração no Notepad ++ (ou qualquer editor de texto de sua preferência)

3) Altere "autocrlf =" para falso.

insira a descrição da imagem aqui

Gene
fonte
31
Por que usar imagens em vez de tags de código? Muito inconveniente
Clint
31
Porque posso adicionar uma grande caixa vermelha na imagem para destacar as coisas.
Gene
21
Usar * text=falsenão remove a definição do texto: deixa o texto definido para o valor da string false. Isso tem o mesmo efeito que deixar o texto não especificado (não especificamente não definido). Usar * -textfornece a configuração especial não definida. Desativar o atributo text em um caminho diz ao git para não tentar nenhuma conversão de fim de linha no check-in ou check-out.
JustAMartin
Obrigado @Gene por esta resposta. Isso tem me deixado louco o dia todo, e esse resolveu para mim!
LeopardSkinPillBoxHat
7
Lamento dizer que não posso agradecer por esta resposta. Custou-me meio dia para descobrir que alguém havia seguido o conselho enganoso. Como @JustAMartin apontou * text=falsenão surtiu efeito. Por favor, corrija a resposta!
Paul B.
47

Uma solução simples é:

  • certifique-se de que core.autocrlf está definido como falso para todos os repositórios:
    git config --global core.autocrlf false
  • clone novamente seu repo e verifique se nenhuma conversão EOL foi feita.
  • ou, desde Git 2.16 (primeiro trimestre de 2018) , mantenha seu repositório atual e faça umgit add --renormalize .

Se houver conversões feitas automaticamente, isso significa que há uma .gitattributes core.eoldiretiva no repo.

Com Git 2.8+ (março de 2016) , verifique se ainda há transformação eol com:

git ls-files --eol
VonC
fonte
2
APENAS NÃO USE autocrlfHOJE! não definido autocrlfé equivalente a false. Você ficou atrás dos movimentos da moda em Git
Lazy Badger de
1
Como acima, tentei fazer isso (embora não com a bandeira global) e não funcionou. versão git é 1.8.5.2.
imallett de
@IanMallett "Neste ponto, parece que a máquina Linux ainda tem CRLF": ele irá até que você normalize seu conteúdo ou o clone (como você fez no Windows)
VonC
11

Eu descobri. Parece que o programa SCP estava convertendo as terminações de linha. Percebi isso quando tentei deliberadamente fazer um arquivo com terminações LF e depois observei que ele apareceu como CRLF quando baixado.

Como essa foi a solução para mim, estou aceitando a resposta, mas as pessoas do futuro também devem consultar as outras respostas para uma solução mais geral.

Imallett
fonte
1
Boa pegada, mais específica do que minha resposta. +1
VonC de
4

De gitattributes (5) Página do manual tópico "Efeitos"

text

Este atributo ativa e controla a normalização de fim de linha. Quando um arquivo de texto é normalizado, suas terminações de linha são convertidas para LF no repositório. Para controlar qual estilo de finalização de linha é usado no diretório de trabalho, use o eolatributo para um único arquivo e a core.eol variável de configuração para todos os arquivos de texto.

Set

Definir o atributo de texto em um caminho permite a normalização de fim de linha e marca o caminho como um arquivo de texto. A conversão de fim de linha ocorre sem adivinhar o tipo de conteúdo.

Unset Desconfigurar o atributo text em um caminho diz ao Git para não tentar nenhuma conversão de fim de linha no check-in ou check-out.

core.autocrlfno novo (1.7.2+) Git não usado core.eole configuração correta | desconfiguração do atributo de texto considerado como forma mais confiável

Texugo Preguiçoso
fonte
No .gitattributesarquivo, eu desativei explicitamente tudo como texto, certo? Além disso, não vejo uma opção para não fazer conversão (embora crlfpossa não ter efeito).
imallett de
6
Algo importante que costuma ser confundido - para remover texte evitar qualquer conversão, você deve definir .gitattributes como * -text e não para * text=false. falsenão é um valor válido para textattribute - git não o reconhecerá e voltará para sua configuração autocrlf padrão. Além disso, depois de alterar o textvalor, você deve fazer backup de todos os arquivos de seu repositório local, fazer um commit e, em seguida, restaurar os arquivos com final de linha corretos conforme necessário e confirmá-los de volta. Então seu fim de linha nunca mais será modificado pelo git.
JustAMartin