Możliwa przyczyna # 1 - Normalizacja zakończenia linii
Jedną z sytuacji, w której może się to zdarzyć, jest to, że dany plik został sprawdzony w repozytorium bez prawidłowej konfiguracji zakończeń linii (1), w wyniku czego plik w repozytorium zawiera niepoprawne zakończenia linii lub mieszane zakończenia linii. Aby potwierdzić, sprawdź, czy git diff
pokazuje tylko zmiany na końcach linii (mogą one być domyślnie niewidoczne, spróbuj git diff | cat -v
zobaczyć znaki powrotu karetki jako literalne ^M
znaki).
Następnie ktoś prawdopodobnie dodał a .gitattributes
lub zmodyfikował to core.autocrlf
ustawienie, aby znormalizować zakończenia linii (2). W oparciu o .gitattributes
konfigurację globalną Git zastosował lokalne zmiany do kopii roboczej, które stosują żądaną normalizację zakończenia linii. Niestety z jakiegoś powodu git reset --hard
nie cofa tych zmian normalizacji linii.
Rozwiązanie
Obejścia, w których resetowane są zakończenia linii lokalnej, nie rozwiążą problemu. Za każdym razem, gdy git „widzi” plik, spróbuje ponownie zastosować normalizację, co powoduje ten sam problem.
Najlepszą opcją jest zezwolenie gitowi na zastosowanie normalizacji, jakiej chce, poprzez znormalizowanie wszystkich zakończeń linii w repozytorium w celu dopasowania ich .gitattributes
i zatwierdzenie tych zmian - zobacz Próbowanie naprawienia zakończeń linii za pomocą gałęzi filtru git, ale bez powodzenia .
Jeśli naprawdę chcesz ręcznie przywrócić zmiany w pliku, wydaje się, że najłatwiejszym rozwiązaniem jest usunięcie zmodyfikowanych plików, a następnie polecenie gitowi przywrócenia ich, chociaż zauważam, że to rozwiązanie nie działa konsekwentnie w 100% czas ( OSTRZEŻENIE: NIE uruchamiaj tego, jeśli zmodyfikowane pliki mają zmiany inne niż zakończenia linii !!):
git status --porcelain | grep "^ M" | cut -c4- | xargs rm
git checkout -- .
Zauważ, że jeśli w pewnym momencie nie znormalizujesz zakończeń linii w repozytorium, nadal będziesz napotykać ten problem.
Możliwa przyczyna # 2 - Rozróżnianie wielkości liter
Drugą możliwą przyczyną jest brak rozróżniania wielkości liter w systemie Windows lub Mac OS / X. Załóżmy na przykład, że w repozytorium istnieje ścieżka taka jak poniżej:
/foo/bar
Teraz ktoś w systemie Linux wprowadza pliki /foo/Bar
(prawdopodobnie z powodu narzędzia do kompilacji lub czegoś, co utworzyło ten katalog) i pcha. W systemie Linux są to teraz dwa osobne katalogi:
/foo/bar/fileA
/foo/Bar/fileA
Zaznaczenie tego repo zewnątrz na Windows lub Mac może spowodować zmodyfikowanej fileA
, która nie może być zresetowany, ponieważ na każdym resecie, Git na kontroli systemu Windows na zewnątrz /foo/bar/fileA
, a następnie, ponieważ system Windows nie uwzględnia wielkości liter, nadpisuje zawartość fileA
z /foo/Bar/fileA
, powodując w nich jest „zmodyfikowany”.
Innym przypadkiem mogą być pojedyncze pliki, które istnieją w repozytorium, które po wyewidencjonowaniu w systemie plików bez rozróżniania wielkości liter nakładałyby się na siebie. Na przykład:
/foo/bar/fileA
/foo/bar/filea
Mogą występować inne podobne sytuacje, które mogą powodować takie problemy.
git w systemach plików bez rozróżniania wielkości liter powinien naprawdę wykryć tę sytuację i pokazać użyteczny komunikat ostrzegawczy, ale obecnie tego nie robi (może się to zmienić w przyszłości - zobacz tę dyskusję i powiązane proponowane łaty na liście mailowej git.git).
Rozwiązanie
Rozwiązaniem jest wyrównanie wielkości plików w indeksie git i wielkości liter w systemie plików Windows. Można to zrobić w systemie Linux, który pokaże prawdziwy stan rzeczy, LUB w systemie Windows za pomocą bardzo użytecznego narzędzia open source Git-Unite . Git-Unite zastosuje niezbędne zmiany wielkości liter do indeksu git, które następnie można zatwierdzić w repozytorium.
(1) był to najprawdopodobniej ktoś z Windows, bez jakiejkolwiek .gitattributes
definicji dla danego pliku, a przy użyciu domyślnego ustawienia globalne dla core.autocrlf
których jest false
(patrz (2)).
(2) http://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/
.
oznacza katalog bieżący, a nie katalog główny