Possível causa nº 1 - Normalização de final de linha
Uma situação em que isso pode acontecer é quando o arquivo em questão foi verificado no repositório sem a configuração correta para terminações de linha (1), resultando em um arquivo no repositório com finais de linha incorretos ou finais de linha misturados. Para confirmar, verifique se git diff
mostra apenas alterações nas terminações de linha (elas podem não estar visíveis por padrão, tente git diff | cat -v
ver os retornos de carro como ^M
caracteres literais ).
Posteriormente, alguém provavelmente adicionou .gitattributes
ou modificou a core.autocrlf
configuração para normalizar as terminações de linha (2). Com base na .gitattributes
configuração global ou, o Git aplicou alterações locais em sua cópia de trabalho que aplicam a normalização de final de linha solicitada. Infelizmente, por algum motivo git reset --hard
, não desfaz essas alterações de normalização de linha.
Solução
As soluções alternativas nas quais as terminações de linha locais são redefinidas não resolverão o problema. Toda vez que o arquivo é "visto" pelo git, ele tenta reaplicar a normalização, resultando no mesmo problema.
A melhor opção é permitir que o git aplique a normalização que deseja, normalizando todas as terminações de linha no repositório para coincidir com as .gitattributes
e comprometendo essas alterações - consulte Tentando corrigir as terminações de linha com git filter-branch, mas sem sorte .
Se você realmente deseja reverter as alterações no arquivo manualmente, a solução mais fácil parece apagar os arquivos modificados e pedir ao git para restaurá-los, embora observe que essa solução parece não funcionar consistentemente 100% dos arquivos. o horário ( AVISO: NÃO execute isso se os arquivos modificados tiverem alterações diferentes das terminações de linha !!):
git status --porcelain | grep "^ M" | cut -c4- | xargs rm
git checkout -- .
Observe que, a menos que você normalize as terminações de linha no repositório em algum momento, você continuará executando esse problema.
Causa possível # 2 - Insensibilidade ao caso
A segunda causa possível é a distinção entre maiúsculas e minúsculas no Windows ou Mac OS / X. Por exemplo, digamos que exista um caminho como o seguinte no repositório:
/foo/bar
Agora, alguém no Linux envia arquivos /foo/Bar
(provavelmente devido a uma ferramenta de construção ou algo que criou esse diretório) e empurra. No Linux, agora são atualmente dois diretórios separados:
/foo/bar/fileA
/foo/Bar/fileA
A verificação desse repositório no Windows ou no Mac pode resultar em modificações fileA
que não podem ser redefinidas, porque a cada redefinição, o git no Windows faz check-out /foo/bar/fileA
e, como o Windows não faz distinção entre maiúsculas e minúsculas, substitui o conteúdo fileA
por /foo/Bar/fileA
, resultando na sua "modificação".
Outro caso pode ser um arquivo individual que existe no repositório que, quando verificado em um sistema de arquivos que não diferencia maiúsculas de minúsculas, se sobrepõe. Por exemplo:
/foo/bar/fileA
/foo/bar/filea
Pode haver outras situações semelhantes que podem causar esses problemas.
O sistema de arquivos que não faz distinção entre maiúsculas e minúsculas deve realmente detectar essa situação e mostrar uma mensagem de aviso útil, mas atualmente não aparece (isso pode mudar no futuro - veja esta discussão e os patches propostos relacionados na lista de discussão do git.git).
Solução
A solução é alinhar o caso dos arquivos no índice git e o caso no sistema de arquivos do Windows. Isso pode ser feito no Linux, que mostrará o verdadeiro estado das coisas, OU no Windows, com o utilitário de código aberto muito útil Git-Unite . O Git-Unite aplicará as alterações de caso necessárias no índice git, que poderão ser confirmadas no repositório.
(1) Isso provavelmente ocorreu por alguém usando o Windows, sem qualquer .gitattributes
definição para o arquivo em questão, e usando a configuração global padrão para a core.autocrlf
qual é false
(consulte (2)).
(2) http://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/
.
significa diretório não diretório raiz atual