'git status' mostra arquivos alterados, mas 'git diff' não

181

Eu já dei uma olhada em todas as perguntas semelhantes. No entanto, verifiquei novamente e algo estranho está definitivamente acontecendo.

Em um servidor (Solaris com Git 1.8.1), clonei o repositório Git e copiei a pasta .git nos meus arquivos ativos existentes. Isso funcionou perfeitamente, eu poderia correr

git status

então

git diff [filename]

para verificar os arquivos diferentes.

Em outro servidor (Solaris com Git 1.7.6), estou fazendo exatamente o mesmo, no entanto

git diff [filename]

não mostra nada, mesmo que o conteúdo do arquivo seja definitivamente diferente. Também testei a adição de um novo arquivo, o comprometimento e a edição. O mesmo problema, git statusmostra o arquivo como alterado, mas git diffnão mostra nada. Se eu baixar o arquivo alterado e executar um diff localmente, obterei a saída do diff.

Oliver P
fonte
9
Está no seu índice? Nesse caso, você pode ver o diff com git diff --cached.
precisa saber é o seguinte
2
git diff --cachedapenas me dá saída em branco também.
28613 Oliver P
git logtambém não dá saída.
Oliver P
Supondo que haja realmente um erro, você poderá criar um exemplo mínimo. Tente reproduzi-lo e compartilhar a amostra.
21413 mheinzerling
1) O modo de arquivo foi alterado? Procure a core.fileModeopção aqui 2) Além disso, estou enfrentando um problema semelhante com a configuração do Console2 (eu o tenho no git) quando o Console2 está realmente em execução. Talvez um bloqueio de arquivo faça com que o git altere o arquivo.
madhead

Respostas:

63

Existem algumas razões pelas quais git statuspode mostrar uma diferença, mas git difftalvez não.

  • O modo (bits de permissão) do arquivo foi alterado - por exemplo, de 777 para 700.

  • O estilo de avanço de linha mudou de CRLF (DOS) para LF (UNIX)

A maneira mais fácil de descobrir o que aconteceu é executar git format-patch HEAD^e ver o que o patch gerado diz.

cmccabe
fonte
11
se os arquivos alterações de permissões se aplicam: git configuração core.filemode false para ignorar a permissão de arquivos
jruzafa
Como você descobriu que a mudança do feed de linha de CRLF para LF é uma das situações em que o status do git mostra uma diferença e o git diff não?
Alex Spurling
A colaboração de colegas de trabalho que usam o Windows ajudará você a descobrir todos os tipos de coisas divertidas sobre terminações de linha. Eu acho que pode ser casos em que "git diff" mostra a alteração de CRLF para LF, no entanto - provavelmente depende da sua configuração. Não trabalho com o Windows há algum tempo, então não sei como são os padrões agora.
cmccabe
59

Para mim, tinha algo a ver com permissões de arquivo. Alguém com Mac / Linux no meu projeto parece confirmar alguns arquivos com permissões não padrão que meu cliente git do Windows não conseguiu reproduzir. A solução para mim foi dizer ao git para ignorar as permissões de arquivo:

git config core.fileMode false

Outro insight: como faço para o Git ignorar alterações no modo de arquivo (chmod)?

Alex Abdugafarov
fonte
Isso resolveu um problema que eu estava tendo com um monte de arquivos, mas acho que foi com o horário de criação / modificação do arquivo.
Derek
Isso resolveu para mim. O valor fileMode parece padrão para true em volumes Mac / Linux e false em volumes Windows. Mudei um projeto do Mac para o Windows e ele precisava ser mudado para falso.
geekinit 30/01
1
Isso também ajudou se você estiver executando o VSCode usando um contêiner do Docker que monta seu diretório no Windows 10. Na parte externa do contêiner, a verificação do status do git mostra corretamente que você não alterou nenhum arquivo. Mas se você verificar o status do git dentro do contêiner, isso mostra que os arquivos foram alterados. A execução do comando acima dentro do contêiner corrigiu meu problema.
Frederick Ollinger
39

Eu tive um problema em que centenas de terminações de linha foram modificadas por algum programa e git difflistaram todos os arquivos de origem como alterados. Depois de corrigir as terminações de linha, git statusainda listamos os arquivos como modificados.

Consegui corrigir esse problema adicionando todos os arquivos ao índice e redefinindo o índice.

git add -A
git reset

core.filemode foi definido como falso.

Jaakko
fonte
Obrigado! Trabalhou como um encanto!
Starwave
1
Eu resolvi com git add --renormalize ., veja minha resposta abaixo.
21419 Stefano M
17

Eu suspeito que há algo errado com sua instalação do Git ou seu repositório.

Tente executar:

GIT_TRACE=2 git <command>

Veja se você obtém algo útil. Se isso não ajudar, basta usar strace e ver o que está errado:

strace git <command>
user1338062
fonte
6
@towi: Como isso valeu uma recompensa para você, eu estaria interessado em ver o que você aprendeu sobre o motivo de suas falhas semelhantes.
Cfi 25/02
5
No meu caso, adicionei o -Fsinalizador à LESSvariável env que diz menos para sair se houver menos de uma tela cheia de informações para mostrar. Como o git usa menos como pager e eu tive uma pequena diferença, nada estava sendo mostrado. Ou eu tive que adicionar -Xao LESSenv que mostra o conteúdo na tela, mesmo depois de menos saídas ou apenas remover -F. GIT_TRACEmostrou que lessestava sendo executado, o que me lembrou que alterei a LESSvariável recentemente. O mesmo motivo na resposta de @ rcwxok, mas queria comentar sobre como GIT_TRACEajudou.
Raghu Dodda 28/09
Essa resposta me dá dica de "pager" e me leva a solução de configuração core.pagerno .gitconfig, que funciona perfeitamente para mim.
ytu
10

Eu tive um problema semelhante: git diffmostraria diferenças, mas git diff <filename>não mostraria. Aconteceu que eu defini LESSuma string incluindo -F( --quit-if-one-screen). A remoção desse sinalizador resolveu o problema.

rcwxok
fonte
1
Em vez de remover -F, adicionar -Xtambém pode funcionar, veja minha resposta abaixo para um caso semelhante.
Avivr
Obrigado por isso! Estava me deixando louco.
hackel
8

Como já observado em uma resposta anterior , essa situação pode surgir devido a problemas de final de linha (CR / LF vs. LF). Resolvi esse problema (na versão 2.22.0 do Git) com este comando:

git add --renormalize .

De acordo com o manual:

       --renormalize
           Apply the "clean" process freshly to all tracked files to
           forcibly add them again to the index. This is useful after
           changing core.autocrlf configuration or the text attribute in
           order to correct files added with wrong CRLF/LF line endings.
           This option implies -u.
Stefano M
fonte
5

Resposta curta

Corrida git add às vezes ajuda.

Exemplo

O status do Git está mostrando os arquivos alterados e o diff do git não está mostrando nada ...

> git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   package.json

no changes added to commit (use "git add" and/or "git commit -a")
> git diff
> 

... executar git add resolve a inconsistência.

> git add
> git status
On branch master
nothing to commit, working directory clean
> 
Shaun Luttin
fonte
2
Isto soa para mim como 'lutando contra os sintomas' em vez de 'cura a doença' ...;)
einjohn
@einjohn O que você acha que é a doença neste caso?
Shaun Luttin
1
A doença pode ser várias coisas. Como mencionado por outros, pode ser um problema de permissão ou algo com as terminações da linha. Também já pode haver mudanças em etapas. No entanto, essa última possibilidade não se encaixa no seu exemplo. No entanto, com a sua solução, você não saberá o motivo (doença), apenas elimine o problema (de uma diferença vazia aparentemente defeituosa (sintomas)). Para ser claro: não estou dizendo que é uma má solução. Pode ajudar alguém, se ele / ela apenas deseja que o problema desapareça. ... espero que tenha esclarecido minha metáfora da doença. :)
einjohn
@einjohn Parece haver finais de linha na maioria das vezes. Parece statuse difftem maneiras separadas de lidar com isso.
Shaun Luttin
5

Eu encontrei este problema. Meu caso foi semelhante ao do LESSassunto postado por rcwxok .

No meu caso, defino a PAGERvariável de ambiente comoPAGER='less -RSF' .

No entanto, ao contrário das respostas anteriores, eu não queria remover a -Fopção, porque eu a coloquei explicitamente na esperança de impedir a exibição do diff emless se for menor que uma tela.

Para obter o resultado desejado, em vez de remover -F, acrescentei -X: PAGER='less -RSFX'. Isso resolveu o git diffproblema e, além disso, evita mostrar diferenças curtas com less.

avivr
fonte
A capitalização parece estranha. Você quer dizer "menos -RSFX" em vez de "MENOS -RSFX"? As opções são o caso correto?
StackzOfZtuff
1
Sim, obrigado, foi um erro. Não tenho certeza de como aconteceu. Agora consertado.
Avivr
3

Acabei de executar em um problema semelhante. git diff filenão mostrou nada porque eu adicionei o arquivo ao índice Git com uma parte do nome em maiúsculas:GeoJSONContainer.js .

Depois, renomeei o nome para GeoJsonContainer.jse as alterações deixaram de ser rastreadas. git diff GeoJsonContainer.jsnão estava mostrando nada. Eu tive que remover o arquivo do índice com um sinalizador de força e adicionar o arquivo novamente:

git rm -f GeoJSONContainer.js
git add GeoJSONContainer.js
Alexandr Lazarev
fonte
2

Você realmente não fez uma pergunta real, mas como esse é um caso de uso geral, estou usando com bastante frequência, eis o que faço. Você pode tentar fazer isso sozinho e ver se o erro persiste.

Minha suposição no seu caso de uso:

Você tem um diretório existente contendo arquivos e diretórios e agora deseja convertê-lo em um repositório Git que é clonado de algum outro lugar sem alterar nenhum dado no diretório atual.

Existem realmente duas maneiras.

.gitRepo clone - mv - git reset --hard

Este método foi o que você fez - para clonar o repositório existente em um diretório vazio e depois mover o .gitdiretório para o diretório de destino. Para trabalhar sem problemas, isso geralmente exige que você execute

git reset --hard

No entanto, isso mudaria o estado dos arquivos no diretório atual. Você pode tentar isso em uma cópia completa / rsync do seu diretório e estudar o que muda. Pelo menos depois, você não deverá mais ver discrepâncias entre git loge status.

Init new repository - apontar para a origem

O segundo é menos perturbador: cdpara o seu destino e inicie um novo repositório com

git init

Então você diz ao novo repositório que ele tem um ancestral em outro lugar:

git remote add origin original_git_repo_path

Então com segurança

git fetch origin master

copiar sobre os dados sem alterar seus arquivos locais. Tudo deve estar bem agora.

Eu sempre recomendo a segunda maneira de ser menos propenso a erros.

cfi
fonte
Você parece sugerir que este é um erro do git . Ok, poderia ser. Eu ainda achava que eu não tinha compreensão adequada git, porque eu não sou tão inteligente como Linus ;-)
towi
@towi: Não, não estou sugerindo que isso seja um erro do Git, nem o contrário. Eu não estou familiarizado com os internos do git. Mas, como regra geral, movendo .gitpastas para outras áreas de trabalho, estamos potencialmente violando as suposições do git. Se isso resultar em comportamento irregular, não podemos culpar o git, temos que nos culpar por fazer truques com o git. O git fornece meios para corrigir isso, por exemplo, o reset --hard. Só que não é isso que queremos. Esta é exatamente a razão pela qual o init/remote addcaminho é recomendado, e tudo está bem.
cfi
@towi e Oliver P: Embora eu entenda que você gostaria que seu caso particular de erro fosse resolvido, às vezes é aconselhável seguir as recomendações gerais - especialmente se elas se encaixarem perfeitamente no seu caso de uso. Também não há perda de dados. E a remote addmaneira de fazer as coisas ainda pode ser aplicada a uma situação confusa como a descrita por Oliver P
cfi 20/02/2013
1
Um voto negativo sem um comentário não ajuda a melhorar essa resposta, nem o site como um todo. Quem recusar, deixe um comentário para que o problema possa ser resolvido.
TPI
1

Eu me deparei com esse problema novamente. Mas desta vez ocorreu por um motivo diferente. Eu copiei os arquivos no repositório para substituir as versões anteriores. Agora posso ver os arquivos modificados, mas o diff não retorna os diffs.

Por exemplo, eu tenho um arquivo mainpage.xaml. No Explorador de Arquivos, colei um novo arquivo mainpage.xaml no arquivo repo atual. Fiz o trabalho em outra máquina e colei o arquivo aqui.
git mostra modificado

O arquivo mostra modificado, mas quando executo o git diff, ele não mostra as alterações. Provavelmente porque o arquivo info do arquivo mudou e o git sabe que não é realmente o mesmo arquivo. Interessante.

git diff não mostra nada

Você pode ver que, quando executo diff no arquivo, ele não mostra nada, apenas retorna o prompt.

raddevus
fonte
1

Eu tive o mesmo problema descrito da seguinte maneira: Se eu digitar

$ git diff

O Git simplesmente retornou ao prompt sem erros.

Se eu digitasse

$ git diff <filename>

O Git simplesmente retornou ao prompt sem erros.

Finalmente, lendo ao redor, notei que git diffrealmente exige mingw64\bin\diff.exeque o trabalho seja feito.

Aqui está o acordo. Estou executando o Windows e havia instalado outro utilitário Bash e ele mudou meu caminho para não apontar mais para o diretório mingw64 \ bin .

Então, se você digitar:

git diff

e ele retorna ao prompt que você pode ter esse problema.

O diff.exe real, que é executado, gitestá localizado no diretório mingw64 \ bin

Por fim, para corrigir isso, copiei meu mingw64\bindiretório para o local em que o Git estava procurando. Tentei e ainda não funcionava.

Então, fechei minha janela do Git Bash e a abri novamente, fui para o mesmo repositório que estava falhando e agora funciona.

raddevus
fonte