«git status» показывает измененные файлы, но «git diff» не показывает

181

Я посмотрел на все подобные вопросы. Тем не менее, я дважды проверил, и определенно происходит что-то странное.

На одном сервере (Solaris с Git 1.8.1) я клонировал репозиторий Git, а затем скопировал папку .git в мои существующие живые файлы. Это работало отлично, я мог бежать

git status

затем

git diff [filename]

проверить любые файлы, которые были разными.

На другом сервере (Solaris с Git 1.7.6) я делаю то же самое, однако

git diff [filename]

ничего не показывает, даже если содержимое файла определенно отличается. Я также протестировал добавление нового файла, его фиксацию и последующее редактирование. Та же проблема, git statusпоказывает файл как измененный, но git diffничего не показывает. Если я загружаю измененный файл и запускаю diff локально, я получаю вывод diff.

Оливер П
источник
9
Это в вашем индексе? Если это так, вы можете просмотреть различия с git diff --cached.
Джеремихаррис
2
git diff --cachedпросто дает мне пустой вывод, а также.
Оливер П
git logтакже не дает никакого выхода.
Оливер П
Предполагая, что действительно есть ошибка, вы сможете создать минимальный пример. Попробуйте воспроизвести его и поделитесь образцом.
Mheinzerling
1) Режим файла был изменен? Ищите core.fileModeвариант здесь 2) Кроме того, я сталкиваюсь с подобной проблемой с конфигурацией Console2 (у меня это есть под git), когда Console2 фактически работает. Может быть, своего рода блокировка файла делает штуку, что файл изменился.
безумный

Ответы:

63

Есть несколько причин, по которым git statusможет показаться разница, но git diffнет.

  • Режим (биты разрешений) файла изменился - например, с 777 до 700.

  • Стиль перевода строки изменен с CRLF (DOS) на LF (UNIX)

Самый простой способ выяснить, что произошло, - это запустить git format-patch HEAD^и посмотреть, что говорит сгенерированный патч.

cmccabe
источник
11
если применяются изменения прав доступа к файлам: git config core.filemode false для игнорирования прав доступа к файлам
jruzafa
Как вы узнали, что перевод строки с CRLF на LF является одной из ситуаций, когда состояние git будет показывать разницу, а изменение git - нет?
Алекс Сперлинг
Наличие сотрудников, использующих Windows, поможет вам узнать все самое интересное о конце строки. Я думаю, что могут быть случаи, когда "git diff" показывает изменение от CRLF до LF, хотя, вероятно, это зависит от вашей конфигурации. Я давно не работал с Windows, поэтому я не знаю, какие сейчас настройки по умолчанию.
cmccabe
59

Для меня это было связано с правами доступа к файлам. Кто-то с Mac / Linux в моем проекте, кажется, фиксирует некоторые файлы с разрешениями не по умолчанию, которые мой git-клиент Windows не смог воспроизвести. Решением для меня было сказать git игнорировать права доступа к файлам:

git config core.fileMode false

Другое понимание: как заставить Git игнорировать изменения режима файла (chmod)?

Алекс Абдугафаров
источник
Это решило проблему, которая у меня была с кучей файлов, хотя я думаю, что это было со временем создания / изменения файла.
Дерек
Это решило это для меня. По умолчанию для значения fileMode установлено значение true для томов Mac / Linux и значение false для томов Windows. Я переместил проект с Mac на Windows, и его нужно было переключить на false.
geekinit
1
Это также помогло, если вы запускаете VSCode с помощью контейнера Docker, который монтирует ваш каталог в Windows 10. Снаружи контейнера проверка состояния git правильно показывает, что вы не изменили никаких файлов. Но если вы проверите состояние git внутри контейнера, оно показывает, что файлы изменены. Выполнение вышеуказанной команды внутри контейнера устранило мою проблему.
Фредерик Оллингер
39

У меня была проблема, когда сотни программ были изменены в конце программы и git diffперечислили все исходные файлы как измененные. После исправления концов строки, git statusвсе равно перечислил файлы как измененные.

Мне удалось решить эту проблему, добавив все файлы в индекс, а затем сбросив индекс.

git add -A
git reset

core.filemode был установлен в ложь.

Jaakko
источник
Спасибо! Работал как шарм!
Starwave
1
Я решил git add --renormalize ., смотри мой ответ ниже.
Стефано М
17

Я подозреваю, что что-то не так с вашей установкой Git или вашим репозиторием.

Попробуйте запустить:

GIT_TRACE=2 git <command>

Посмотри, получишь ли ты что-нибудь полезное. Если это не поможет, просто используйте strace и посмотрите, что идет не так:

strace git <command>
user1338062
источник
6
@towi: Поскольку это стоило вам щедрости, мне было бы интересно узнать, что вы узнали о причине подобных неудач.
CFI
5
В моем случае я добавил -Fфлаг в LESSпеременную env, который сообщает меньше, чтобы выйти, если для отображения информации требуется менее одного экрана. Поскольку git использует меньше как пейджер, и у меня был маленький diff, ничего не показывалось. Либо мне пришлось добавить -Xв LESSenv, который показывает содержимое на экране даже после меньшего количества выходов, либо просто удалить -F. GIT_TRACEпоказал, lessчто выполняется, что напомнило мне, что я изменилLESS недавно переменную. Та же причина в ответе @ rcwxok, но хотел прокомментировать, как это GIT_TRACEпомогло.
Рагху Додда
Этот ответ дает мне намек на «пейджер» и приводит меня к решению о настройке core.pagerв .gitconfig, который прекрасно работает для меня.
Ytu
10

У меня была похожая проблема: git diffпоказывали бы различия, но git diff <filename>не показывали . Оказалось, что я установил LESSстроку, включающую -F( --quit-if-one-screen). Снятие этого флага решило проблему.

rcwxok
источник
1
Вместо удаления -F, добавление -Xможет также работать, см. Мой ответ ниже для аналогичного случая.
Авивр
Спасибо тебе за это! Сводил меня с ума.
хакель
9

Как уже отмечалось в предыдущем ответе , эта ситуация может возникнуть из-за проблем с окончанием строки (CR / LF против LF). Я решил эту проблему (под Git версии 2.22.0) с помощью этой команды:

git add --renormalize .

Согласно инструкции:

       --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.
Стефано М
источник
Это новый лучший ответ.
PHP
5

Короткий ответ

Бег git add иногда помогает.

пример

Git показывает состояние измененных файлов, а git diff ничего не показывает ...

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

... запуск git add разрешает несоответствие.

> git add
> git status
On branch master
nothing to commit, working directory clean
> 
Шон Луттин
источник
2
Для меня это звучит как «борьба с симптомами», а не «лечение болезни» ...;)
einjohn
@einjohn Как вы думаете, болезнь в этом случае?
Шон Луттин
1
Болезнь может быть несколько вещей. Как уже упоминалось, это может быть проблема с правами доступа или что-то с окончанием строки. Также могут быть уже постановочные изменения. Однако эта последняя возможность не подходит вашему примеру. Тем не менее, с вашим решением вы не будете знать причину (болезнь), вы просто устраняете проблему (кажущегося ошибочным пустого различия (симптомы)). Поясню: я не говорю, что это плохое решение. Это может помочь кому-то, если он / она просто хочет, чтобы проблема исчезла. ... надеюсь, я пролил некоторый свет на свою метафору болезни. :)
einjohn
@einjohn Большую часть времени это, кажется, конец строки. Кажется statusи diffесть отдельные способы справиться с ними.
Шон Луттин,
5

Я столкнулся с этой проблемой. Мой случай был похож на LESSвопрос, опубликованный rcwxok .

В моем случае я установил PAGERпеременную окружения на PAGER='less -RSF'.

Однако, в отличие от предыдущих ответов, я не хотел удалять эту -Fопцию, потому что я явно поместил ее там в надежде предотвратить показ различий, lessесли он короче, чем скрин.

Для того, чтобы получить желаемый результат, а не удалять -F, я добавил -X: PAGER='less -RSFX'. Это решило git diffпроблему и, кроме того, не позволяет показывать короткие различия less.

avivr
источник
Капитализация кажется странной. Вы имеете в виду «менее -RSFX» вместо «МЕНЬШЕ-RSFX»? Варианты правильного случая?
StackzOfZtuff
1
Да, спасибо, это была ошибка. Не уверен, как это случилось. Сейчас исправлено.
Авивр
3

Я только что столкнулся с подобной проблемой. git diff fileничего не показывал, потому что я добавил файл в индекс Git с какой-то частью его имени в верхнем регистре:GeoJSONContainer.js .

После этого я переименовал его, GeoJsonContainer.jsи изменения перестали отслеживаться. git diff GeoJsonContainer.jsничего не показывал. Мне пришлось удалить файл из индекса с флагом принудительной установки и снова добавить файл:

git rm -f GeoJSONContainer.js
git add GeoJSONContainer.js
Александр Лазарев
источник
2

Вы на самом деле не задавали актуальный вопрос, но так как это общий случай использования, я использую довольно часто вот что я делаю. Вы можете попробовать это сами и посмотреть, не исчезнет ли ошибка.

Мое предположение о вашем случае использования:

У вас есть существующий каталог, содержащий файлы и каталоги, и теперь вы хотите преобразовать его в репозиторий Git, который клонируется из другого места без изменения каких-либо данных в вашем текущем каталоге.

Есть действительно два пути.

.gitРепозиторий клонов - mv - git reset --hard

Этот метод - то, что вы сделали - клонировать существующий репозиторий в пустой каталог, а затем переместить .gitкаталог в каталог назначения. Чтобы работать без проблем, это обычно требует от вас, чтобы запустить

git reset --hard

Однако это изменит состояние файлов в вашем текущем каталоге. Вы можете попробовать это в полной копии / rsync вашего каталога и изучить, какие изменения. По крайней мере, после этого вы больше не должны видеть расхождений между git logи status.

Инициировать новый репозиторий - указать на источник

Второе менее тревожно: cdв пункт назначения и запустите новый репозиторий с

git init

Затем вы говорите этому новому хранилищу, что у него есть предок в другом месте:

git remote add origin original_git_repo_path

Тогда благополучно

git fetch origin master

копировать данные без изменения локальных файлов. Теперь все должно быть хорошо.

Я всегда рекомендую второй способ, чтобы быть менее подверженным ошибкам.

CFI
источник
Вы, кажется, подразумеваете, что это ошибка мерзавца . Хорошо, может быть. Я все еще предполагал, что у меня не было должного понимания
мерзавца
@towi: Нет, я не намекаю на то, что это ошибка мерзавца, и не намекаю на обратное. Я не знаком с внутренностями мерзавца. Но, как правило, перемещая .gitпапки в другие рабочие области, мы потенциально нарушаем допущения git. Если это приводит к нестабильному поведению, мы не можем винить git, мы должны винить себя за то, что играем с git. Git предоставляет средства для исправления этого, например reset --hard. Просто это не то, что мы хотим. Это как раз та причина, по которой init/remote addпуть рекомендуется, и все хорошо.
Cfi
@towi и Oliver P: хотя я понимаю, что вы хотели бы, чтобы ваш конкретный случай ошибки был решен, иногда советуют просто следовать общим рекомендациям, особенно если они идеально подходят для вашего варианта использования. Там также нет потери данных. И remote addспособ делать вещи по- прежнему может быть применен к перепутались ситуациям , подобные описанному Оливер P
CFI
1
Понижение рейтинга без комментариев не поможет улучшить этот ответ ни сайту в целом. Кто бы ни отрицал, пожалуйста, оставьте комментарий, чтобы проблема могла быть решена.
Cfi
1

Я снова наткнулся на эту проблему. Но на этот раз это произошло по другой причине. Я скопировал файлы в репозиторий, чтобы перезаписать предыдущие версии. Теперь я вижу, что файлы изменены, но diff не возвращает diff.

Например, у меня есть файл mainpage.xaml. В проводнике я вставил новый файл mainpage.xaml поверх файла в моем текущем репо. Я сделал работу на другом компьютере и просто вставил файл сюда.
мерзавец показывает модифицированный

Файл показывает измененный, но когда я запускаю git diff, он не показывает изменения. Возможно, это связано с тем, что информация о файле в файле изменилась, и git знает, что это не тот же файл. Интересный.

git diff ничего не показывает

Вы можете видеть, что когда я запускаю diff для файла, он ничего не показывает, просто возвращает приглашение.

raddevus
источник
1

Я описал эту проблему следующим образом: если я набрал

$ git diff

Git просто вернулся к приглашению без ошибок.

Если бы я напечатал

$ git diff <filename>

Git просто вернулся к приглашению без ошибок.

Наконец, читая вокруг, я заметил, что на git diffсамом деле вызываетmingw64\bin\diff.exe сделать работу.

Вот сделка. Я использую Windows и установил другую утилиту Bash, и она изменила мой путь, чтобы он больше не указывал на мой mingw64 \ bin .

Так что если вы наберете:

git diff

и он просто возвращается к подсказке, у вас может быть эта проблема.

Фактический diff.exe, который запускается, gitнаходится в вашем каталоге mingw64 \ bin

Наконец, чтобы это исправить, я скопировал mingw64\bin каталог в то место, где его искал Git. Я попробовал, но он все еще не работал.

Затем я закрыл окно Git Bash и снова открыл его, перешел в мой тот же репозиторий, который вышел из строя, и теперь он работает.

raddevus
источник