'git status' affiche les fichiers modifiés, mais pas 'git diff'

181

J'ai examiné toutes les questions similaires. Cependant, j'ai vérifié deux fois et quelque chose d'étrange se passe définitivement.

Sur un serveur (Solaris avec Git 1.8.1), j'ai cloné le référentiel Git puis copié le dossier .git dans mes fichiers live existants. Cela a parfaitement fonctionné, je pourrais courir

git status

puis

git diff [filename]

pour vérifier tous les fichiers qui étaient différents.

Sur un autre serveur (Solaris avec Git 1.7.6), je fais exactement la même chose cependant

git diff [filename]

ne montre rien, même si le contenu du fichier est définitivement différent. J'ai également testé l'ajout d'un nouveau fichier, le valider, puis le modifier. Le même problème, git statusmontre le fichier comme modifié, mais git diffne montre rien. Si je télécharge le fichier modifié et exécute un diff localement, j'obtiens une sortie diff.

Oliver P
la source
9
Est-ce dans votre index? Si tel est le cas, vous pouvez afficher les différences avec git diff --cached.
jeremyharris
2
git diff --cachedme donne juste une sortie vierge aussi.
Oliver P
git logne donne pas non plus de sortie.
Oliver P
En supposant qu'il y ait vraiment un bogue, vous devriez être capable de créer un exemple minimal. Essayez de le reproduire et de partager l'échantillon.
mheinzerling
1) Le mode fichier a été changé? Recherchez l' core.fileModeoption ici 2) En outre, je suis confronté à un problème similaire avec la configuration de Console2 (je l'ai sous git) lorsque Console2 est en cours d'exécution. Peut-être qu'une sorte de verrouillage de fichier rend git à ce que le fichier a changé.
madhead

Réponses:

63

Il y a quelques raisons pour lesquelles cela git statuspourrait montrer une différence mais git diffpas.

  • Le mode (bits d'autorisation) du fichier a changé - par exemple, de 777 à 700.

  • Le style de saut de ligne est passé de CRLF (DOS) à LF (UNIX)

Le moyen le plus simple de découvrir ce qui s'est passé est d'exécuter git format-patch HEAD^et de voir ce que dit le correctif généré.

cmccabe
la source
11
si les fichiers d'autorisation de modification s'appliquent: git config core.filemode false pour ignorer l'autorisation des fichiers
jruzafa
Comment avez-vous découvert que le changement de saut de ligne de CRLF à LF est l'une des situations où l'état de git affichera une différence et git diff ne le sera pas?
Alex Spurling
Avoir des collègues qui utilisent Windows vous aidera à découvrir toutes sortes de choses amusantes sur les fins de ligne. Je pense qu'il pourrait y avoir des cas où "git diff" montre le changement de CRLF à LF, cependant - cela dépend probablement de votre configuration. Je n'ai pas travaillé avec Windows depuis un moment, donc je ne sais pas à quoi ressemblent les valeurs par défaut.
cmccabe
59

Pour moi, cela avait quelque chose à voir avec les autorisations de fichiers. Quelqu'un avec Mac / Linux sur mon projet semble valider certains fichiers avec des autorisations non par défaut que mon client git Windows n'a pas pu reproduire. La solution pour moi était de dire à git d'ignorer les autorisations de fichiers:

git config core.fileMode false

Autre aperçu: Comment faire pour que Git ignore les changements de mode de fichier (chmod)?

Alex Abdugafarov
la source
Cela a résolu un problème que j'avais avec un tas de fichiers, même si je pense que c'était avec le fichier créé / modifié à la place.
Derek
Cela a résolu le problème pour moi. La valeur fileMode semble être par défaut true sur les volumes Mac / Linux et false sur les volumes Windows. J'ai déplacé un projet de Mac vers Windows et il devait être basculé sur false.
geekinit le
1
Cela a également aidé si vous exécutez VSCode en utilisant un conteneur Docker qui monte votre répertoire sur Windows 10. À l'extérieur du conteneur, la vérification de l'état de git montre correctement que vous n'avez modifié aucun fichier. Mais si vous vérifiez l'état de git dans le conteneur, cela montre que les fichiers ont été modifiés. L'exécution de la commande ci-dessus dans le conteneur a résolu mon problème.
Frederick Ollinger
39

J'ai eu un problème où des centaines de fins de ligne ont été modifiées par un programme et git diffrépertorié tous les fichiers source comme modifiés. Après avoir corrigé les fins de ligne, git statustoujours répertorié les fichiers comme modifiés.

J'ai pu résoudre ce problème en ajoutant tous les fichiers à l'index, puis en réinitialisant l'index.

git add -A
git reset

core.filemode a été défini sur false.

Jaakko
la source
Je vous remercie! A travaillé comme un charme!
Starwave
1
J'ai résolu avec git add --renormalize ., voir ma réponse ci-dessous.
Stefano M
17

Je soupçonne qu'il y a quelque chose qui ne va pas avec votre installation Git ou votre référentiel.

Essayez de courir:

GIT_TRACE=2 git <command>

Voyez si vous obtenez quelque chose d'utile. Si cela ne vous aide pas, utilisez simplement strace et voyez ce qui ne va pas:

strace git <command>
user1338062
la source
6
@towi: Puisque cela valait une prime pour vous, je serais intéressé de voir ce que vous avez appris sur la raison de vos échecs similaires.
cfi
5
Dans mon cas, j'ai ajouté le -Fdrapeau à la LESSvariable env qui indique moins de quitter s'il y a moins d'un écran plein d'informations à afficher. Puisque git utilise moins comme pager, et que j'avais un petit diff, rien n'était affiché. Soit je devais ajouter -Xà l' LESSenvironnement qui montre le contenu à l'écran même après moins de sorties ou simplement supprimer -F. GIT_TRACEa montré que lessc'était en cours d'exécution, ce qui m'a rappelé que j'avais changé la LESSvariable récemment. Même raison dans la réponse de @ rcwxok, mais je voulais un commentaire sur la façon dont cela a été GIT_TRACEaidé.
Raghu Dodda
Cette réponse me donne un soupçon de "pager" et m'amène à la solution de mise core.pageren place .gitconfig, qui fonctionne parfaitement pour moi.
ytu
10

J'avais un problème similaire: git diffmontrerait des différences, mais git diff <filename>pas. Il s'est avéré que j'avais défini LESSune chaîne comprenant -F( --quit-if-one-screen). La suppression de cet indicateur a résolu le problème.

rcwxok
la source
1
Au lieu de supprimer -F, l'ajout -Xpeut également fonctionner, voir ma réponse ci-dessous pour un cas similaire.
avivr
Merci pour ça! Cela me rendait fou.
hackel
9

Comme déjà noté dans une réponse précédente , cette situation peut survenir en raison de problèmes de fin de ligne (CR / LF vs LF). J'ai résolu ce problème (sous Git version 2.22.0) avec cette commande:

git add --renormalize .

Selon le manuel:

       --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
la source
C'est la nouvelle meilleure réponse.
PHP
5

Réponse courte

Courir git addaide parfois.

Exemple

L'état de Git affiche les fichiers modifiés et git diff n'affiche rien ...

> 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
> 

... exécuter git add résout l'incohérence.

> git add
> git status
On branch master
nothing to commit, working directory clean
> 
Shaun Luttin
la source
2
Cela me ressemble à `` combattre les symptômes '' au lieu de `` guérir la maladie '' ...;)
einjohn
@einjohn Quelle est selon vous la maladie dans ce cas?
Shaun Luttin
1
La maladie peut être plusieurs choses. Comme mentionné par d'autres, cela peut être un problème d'autorisations ou quelque chose avec les fins de ligne. Il pourrait également s'agir de changements déjà par étapes. Cependant, cette dernière possibilité ne correspond pas à votre exemple. Néanmoins, avec votre solution, vous ne saurez pas la raison (maladie), vous éliminez simplement le problème (d'un diff vide apparemment défectueux (symptômes)). Pour être clair: je ne dis pas que c'est une mauvaise solution. Cela peut aider quelqu'un s'il veut simplement que le problème disparaisse. ... j'espère avoir fait la lumière sur ma métaphore de la maladie. :)
einjohn
@einjohn Il semble que ce soit des fins de ligne la plupart du temps. Il semble statuset diffavoir des façons distinctes de les gérer.
Shaun Luttin
5

J'ai rencontré ce problème. Mon cas était semblable à la LESSquestion publié par rcwxok .

Dans mon cas, j'ai défini la PAGERvariable d'environnement sur PAGER='less -RSF'.

Cependant, contrairement aux réponses précédentes, je ne voulais pas supprimer l' -Foption, car je l'ai explicitement mise là-bas dans l'espoir d'éviter d'afficher le différentiel lesss'il est plus court qu'un écran.

Pour obtenir le résultat souhaité, au lieu de supprimer -F, j'ai ajouté -X: PAGER='less -RSFX'. Cela a à la fois résolu le git diffproblème et en plus cela empêche d'afficher des différences courtes avec less.

avivr
la source
La capitalisation semble bizarre. Voulez-vous dire "moins -RSFX" au lieu de "MOINS -RSFX"? Les options sont-elles le bon cas?
StackzOfZtuff
1
Oui, merci, c'était une erreur. Je ne sais pas comment c'est arrivé. Maintenant corrigé.
avivr
3

Je viens de courir dans un problème similaire. git diff filea montré rien parce que j'ai ajouté le fichier à l'index Git avec une partie de son nom en majuscules: GeoJSONContainer.js.

Ensuite, je l'ai renommé GeoJsonContainer.jset les modifications ont cessé d'être suivies. git diff GeoJsonContainer.jsne montrait rien. J'ai dû supprimer le fichier de l'index avec un indicateur de force et ajouter à nouveau le fichier:

git rm -f GeoJSONContainer.js
git add GeoJSONContainer.js
Alexandr Lazarev
la source
2

Vous n'avez pas vraiment posé de question, mais comme il s'agit d'un cas d'utilisation général que j'utilise assez souvent, voici ce que je fais. Vous pouvez essayer cela vous-même et voir si l'erreur persiste.

Mon hypothèse sur votre cas d'utilisation:

Vous avez un répertoire existant contenant des fichiers et des répertoires et vous souhaitez maintenant le convertir en un dépôt Git qui est cloné à partir d'un autre endroit sans changer aucune donnée dans votre répertoire actuel.

Il y a vraiment deux façons.

Cloner le dépôt - mv .git- git reset --hard

Cette méthode est ce que vous avez fait - pour cloner le référentiel existant dans un répertoire vide, puis déplacer le .gitrépertoire dans le répertoire de destination. Pour travailler sans problème, cela vous oblige généralement à exécuter

git reset --hard

Cependant, cela changerait l'état des fichiers dans votre répertoire actuel. Vous pouvez essayer ceci sur une copie / rsync complète de votre répertoire et étudier les changements. Au moins après, vous ne devriez plus voir les écarts entre git loget status.

Init nouveau référentiel - pointer vers l'origine

Le second est moins dérangeant: cddans votre destination, et démarrez un nouveau référentiel avec

git init

Ensuite, vous dites à ce nouveau référentiel, qu'il a un ancêtre ailleurs:

git remote add origin original_git_repo_path

Puis en toute sécurité

git fetch origin master

pour copier les données sans modifier vos fichiers locaux. Tout devrait aller bien maintenant.

Je recommande toujours la deuxième manière d'être moins sujette aux erreurs.

cfi
la source
Vous semblez laisser entendre que c'est une erreur git . Ok, ça pourrait être. J'ai toujours supposé que je manquais de compréhension git, car je ne suis pas aussi intelligent que Linus ;-)
Towi
@towi: Non, je n'implique pas qu'il s'agit d'une erreur git, et je n'implique pas non plus le contraire. Je ne suis pas familier avec les composants internes de git. Mais en règle générale, en déplaçant les .gitdossiers dans d'autres zones de travail, nous violons potentiellement les hypothèses de git. Si cela entraîne un comportement erratique, nous ne pouvons pas blâmer git, nous devons nous blâmer d'avoir joué des tours avec git. git fournit des moyens pour résoudre ce problème, par exemple reset --hard. C'est juste que ce n'est pas ce que nous voulons. C'est exactement la raison pour laquelle la init/remote addvoie est recommandée, et tout va bien.
cfi
@towi et Oliver P: Bien que je comprenne que vous souhaitiez que votre cas d'erreur particulier soit résolu, il est parfois conseillé de suivre les recommandations générales, surtout si elles correspondent parfaitement à votre cas d'utilisation. Il n'y a pas non plus de perte de données. Et la remote addfaçon de faire peut toujours être appliquée à une situation
désordonnée
1
Un vote négatif sans commentaire n'aide pas à améliorer cette réponse, ni le site dans son ensemble. Quiconque vote contre, veuillez laisser un commentaire afin que le problème puisse être résolu.
cfi
1

Je suis de nouveau tombé sur ce problème. Mais cette fois, cela s'est produit pour une raison différente. J'avais copié des fichiers dans le dépôt pour écraser les versions précédentes. Maintenant, je peux voir que les fichiers sont modifiés mais diff ne renvoie pas les diffs.

Par exemple, j'ai un fichier mainpage.xaml. Dans l'Explorateur de fichiers, j'ai collé un nouveau fichier mainpage.xaml sur celui de mon dépôt actuel. J'ai fait le travail sur une autre machine et je viens de coller le fichier ici.
git montre modifié

Le fichier est modifié, mais lorsque j'exécute git diff, il n'affiche pas les modifications. C'est probablement parce que le fichier info du fichier a changé et que git sait que ce n'est pas vraiment le même fichier. Intéressant.

git diff ne montre rien

Vous pouvez voir que lorsque j'exécute diff sur le fichier, il ne montre rien, renvoie simplement l'invite.

raddevus
la source
1

J'ai eu ce même problème décrit de la manière suivante: Si j'ai tapé

$ git diff

Git est simplement retourné à l'invite sans erreur.

Si j'ai tapé

$ git diff <filename>

Git est simplement retourné à l'invite sans erreur.

Enfin, en lisant autour de moi, j'ai remarqué que cela git diffappelle en fait le mingw64\bin\diff.exeà faire le travail.

Voici l'affaire. J'exécute Windows et j'avais installé un autre utilitaire Bash et il a changé mon chemin pour qu'il ne pointe plus vers mon répertoire mingw64 \ bin .

Donc, si vous tapez:

git diff

et il revient simplement à l'invite, vous pouvez avoir ce problème.

Le diff.exe réel qui est exécuté par gitse trouve dans votre répertoire mingw64 \ bin

Enfin, pour résoudre ce problème, j'ai en fait copié mon mingw64\binrépertoire à l'emplacement où Git le recherchait. Je l'ai essayé et cela n'a toujours pas fonctionné.

Ensuite, j'ai fermé ma fenêtre Git Bash et l' ai rouverte dans mon même référentiel qui échouait et maintenant cela fonctionne.

raddevus
la source