Можлива причина №1 - Нормалізація закінчення рядків
Одна з ситуацій, в якій це може статися, - коли відповідний файл був зареєстрований у сховище без правильної конфігурації для закінчень рядків (1), в результаті чого файл у сховищі має неправильні закінчення рядків або змішані закінчення рядків. Щоб підтвердити, переконайтеся, що git diffвідображаються лише зміни в закінченнях рядків (вони можуть не бути видимими за замовчуванням, спробуйте git diff | cat -vпобачити повернення каретки як буквальне^M символи).
Згодом хтось, ймовірно, додав .gitattributesабо змінив core.autocrlfналаштування для нормалізації закінчень рядків (2). На основі .gitattributesконфігурації або глобальної конфігурації, Git застосував локальні зміни до вашої робочої копії, які застосовують рядок, що закінчує запит на нормалізацію. На жаль, чомусьgit reset --hard не скасовує ці зміни в нормалізації лінії.
Рішення
Обхідні шляхи, в яких скидаються закінчення локальних рядків, не вирішать проблему. Кожен раз, коли файл "бачить" git, він намагатиметься повторно застосувати нормалізацію, внаслідок чого виникає та сама проблема.
Найкращий варіант - дозволити git застосувати нормалізацію, яку він хоче, шляхом нормалізації всіх закінчень рядків у репо, щоб вони відповідали .gitattributes, та внесення цих змін - див. Спроба виправити закінчення рядків за допомогою git filter-branch, але не маючи удачі .
Якщо ви дійсно хочете спробувати повернути зміни до файлу вручну, то, як видається, найпростішим рішенням є видалити змінені файли, а потім сказати git відновити їх, хоча зауважу, це рішення, здається, не працює стабільно на 100% час ( ПОПЕРЕДЖЕННЯ: НЕ запускайте це, якщо ваші змінені файли мають інші зміни, ніж закінчення рядків !!):
git status --porcelain | grep "^ M" | cut -c4- | xargs rm
git checkout -- .
Зауважте, що якщо ви не нормалізуєте закінчення рядків у сховищі в якийсь момент, ви продовжуєте працювати з цією проблемою.
Можлива причина №2 - Нечутливість до справи
Друга можлива причина - нечутливість випадків у Windows чи Mac OS / X. Наприклад, скажіть, що в сховищі існує такий шлях, як наступний:
/foo/bar
Тепер хтось із Linux здійснює /foo/Barвведення файлів у файли (можливо, завдяки інструменту збирання або тому, що створив цей каталог) і натискає. В Linux це фактично зараз два окремі каталоги:
/foo/bar/fileA
/foo/Bar/fileA
Перевірка цього репо з на Windows , Mac або може привести до модифікованого , fileAякі не можуть бути скинуті, тому що на кожному скиданні, мерзотника на Windows , перевіряє /foo/bar/fileA, а потім з - за Windows , не чутлива до регістру, переписує вміст fileAз/foo/Bar/fileA , в результаті чого в них бути «змінені».
Іншим випадком можуть бути окремі файли (файли), які існують у репо, які при перевірці на файлову систему, нечутливу до справ, перекриватимуться. Наприклад:
/foo/bar/fileA
/foo/bar/filea
Можуть бути й інші подібні ситуації, які можуть спричинити такі проблеми.
git на нечутливі до випадку файлові системи повинні дійсно виявити цю ситуацію та показати корисне попереджувальне повідомлення, але наразі цього немає (це може змінитися в майбутньому - див. цю дискусію та пов'язані із запропонованими виправленнями у списку розсилки git.git).
Рішення
Рішення полягає в тому, щоб привести у відповідність регістр файлів у індексі git та регістр файлової системи Windows. Це можна зробити в Linux, який покаже справжній стан речей, АБО в Windows з дуже корисною утилітою з відкритим кодом Git-Unite . Git-Unite застосує необхідні зміни до індексу git, які потім можуть бути передані репо.
(1) Це, швидше за все, хтось, хто використовує Windows, без будь-якого .gitattributesвизначення відповідного файлу та використовував глобальну настройку за замовчуванням, core.autocrlfяка є false(див. (2)).
(2) http://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/
.означає, що поточний каталог не є кореневим каталогом