Можлива причина №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/
.
означає, що поточний каталог не є кореневим каталогом