„Stan git” pokazuje zmienione pliki, ale „git diff” nie

181

Rzuciłem okiem na wszystkie podobne pytania. Jednak dwukrotnie sprawdziłem i zdecydowanie dzieje się coś dziwnego.

Na jednym serwerze (Solaris z Git 1.8.1) sklonowałem repozytorium Git, a następnie skopiowałem folder .git do moich istniejących plików live. To działało idealnie, mogłem biegać

git status

następnie

git diff [filename]

aby sprawdzić inne pliki.

Na innym serwerze (Solaris z Git 1.7.6) robię jednak dokładnie to samo

git diff [filename]

nic nie pokazuje, nawet jeśli zawartość pliku jest zdecydowanie inna. Testowałem też dodawanie nowego pliku, zatwierdzanie go, a następnie edycję. Ten sam problem git statuspokazuje plik jako zmieniony, ale git diffnic nie pokazuje. Jeśli pobieram zmieniony plik i lokalnie uruchamiam diff, otrzymuję dane wyjściowe diff.

Oliver P
źródło
9
Czy to jest w twoim indeksie? Jeśli tak, możesz wyświetlić różnicę za pomocą git diff --cached.
jeremyharris
2
git diff --cachedpo prostu daje mi również pusty wynik.
Oliver P
git logrównież nie daje wyjścia.
Oliver P
Zakładając, że naprawdę jest błąd, powinieneś być w stanie stworzyć minimalny przykład. Spróbuj to odtworzyć i udostępnij próbkę.
mheinzerling
1) Tryb pliku został zmieniony? Poszukaj core.fileModeopcji tutaj 2) Również mam podobny problem z konfiguracją Console2 (mam ją pod git), gdy Console2 faktycznie działa. Może coś w rodzaju blokady pliku powoduje, że git się zmienił.
szalony

Odpowiedzi:

63

Istnieje kilka powodów, dla których git statusmoże się to różnić, ale git diffnie.

  • Zmienił się tryb (bity uprawnień) pliku - na przykład z 777 na 700.

  • Zmieniono styl wysuwu wiersza z CRLF (DOS) na LF (UNIX)

Najłatwiejszym sposobem sprawdzenia, co się stało, jest uruchomienie git format-patch HEAD^i sprawdzenie, co mówi wygenerowana łatka.

cmccabe
źródło
11
jeśli zmiany dotyczą plików uprawnień: git config core.filemode false dla ignorowania uprawnień plików
jruzafa
Jak dowiedziałeś się, że zmiana znaku nowego wiersza z CRLF na LF jest jedną z sytuacji, w których status git pokaże różnicę, a różnica git nie?
Alex Spurling
Współpracownicy korzystający z systemu Windows pomogą Ci dowiedzieć się wielu ciekawych rzeczy o zakończeniach linii. Myślę, że mogą być przypadki, w których "git diff" pokazuje zmianę z CRLF na LF - prawdopodobnie zależy to od twojej konfiguracji. Od jakiegoś czasu nie pracowałem z systemem Windows, więc nie wiem, jakie są teraz ustawienia domyślne.
cmccabe
59

Dla mnie miało to coś wspólnego z uprawnieniami do plików. Ktoś z systemem Mac / Linux w moim projekcie wydaje się zatwierdzać niektóre pliki z uprawnieniami innymi niż domyślne, których mój klient git systemu Windows nie mógł odtworzyć. Rozwiązaniem dla mnie było powiedzenie gitowi ignorowania uprawnień do plików:

git config core.fileMode false

Inne spostrzeżenia: Jak sprawić, by Git ignorował zmiany trybu plików (chmod)?

Alex Abdugafarov
źródło
To rozwiązało problem, który miałem z kilkoma plikami, chociaż myślę, że zamiast tego dotyczyło to czasu utworzenia / modyfikacji pliku.
Derek
To rozwiązało to dla mnie. Wartość fileMode wygląda na domyślną true na woluminach Mac / Linux i false na woluminach Windows. Przeniosłem projekt z Maca do Windowsa i trzeba go było zmienić na fałsz.
geekinit
1
Pomogło to również, jeśli korzystasz z VSCode przy użyciu kontenera Docker, który montuje Twój katalog w systemie Windows 10. Na zewnątrz kontenera sprawdzenie statusu git poprawnie pokazuje, że nie zmieniłeś żadnych plików. Ale jeśli sprawdzisz status git w kontenerze, pokazuje, że pliki zostały zmienione. Uruchomienie powyższego polecenia w kontenerze rozwiązało mój problem.
Frederick Ollinger
39

Miałem problem polegający na tym, że setki zakończeń linii zostały zmodyfikowane przez jakiś program i git diffwymieniono wszystkie pliki źródłowe jako zmienione. Po naprawieniu zakończeń linii,git status nadal wyświetlał pliki jako zmodyfikowane.

Udało mi się rozwiązać ten problem, dodając wszystkie pliki do indeksu, a następnie resetując indeks.

git add -A
git reset

core.filemode został ustawiony na false.

Jaakko
źródło
Dziękuję Ci! Działał jak urok!
Starwave,
1
Rozwiązałem z git add --renormalize ., zobacz moją odpowiedź poniżej.
Stefano M
17

Podejrzewam, że coś jest nie tak z instalacją Gita lub repozytorium.

Spróbuj biegać:

GIT_TRACE=2 git <command>

Zobacz, czy znajdziesz coś przydatnego. Jeśli to nie pomoże, po prostu użyj strace i zobacz, co się dzieje:

strace git <command>
user1338062
źródło
6
@towi: Ponieważ było to dla ciebie warte nagrody, chciałbym zobaczyć, czego się dowiedziałeś o przyczynach twoich podobnych niepowodzeń.
cfi
5
W moim przypadku dodałem -Fflagę do LESSzmiennej env, która mówi less do wyjścia, jeśli jest mniej niż jeden ekran pełen informacji do pokazania. Ponieważ git używa mniej jako pager, a ja miałem mały różnicę, nic nie było pokazywane. Albo musiałem dodać -Xdo LESSenv, który wyświetla zawartość na ekranie nawet po mniejszej liczbie wyjść, albo po prostu usunąć -F. GIT_TRACEpokazał, że lessjest wykonywany, co przypomniało mi, że LESSostatnio zmieniłem zmienną. Ten sam powód w odpowiedzi @ rcwxok, ale chciałem skomentować, jak GIT_TRACEpomogło.
Raghu Dodda
Odpowiedź ta zapewnia mi podpowiedź „pager” i prowadzi mnie do rozwiązania z ustawieniem core.pagerw .gitconfig, który działa idealnie dla mnie.
ytu
10

Miałem podobny problem: git diffpokazywałbym różnice, ale git diff <filename>nie. Okazało się, że ustawiłem LESSna ciąg zawierający -F( --quit-if-one-screen). Usunięcie tej flagi rozwiązało problem.

rcwxok
źródło
1
Zamiast usuwać -F, dodawanie -Xmoże również działać, zobacz moją odpowiedź poniżej na podobny przypadek.
avivr
Dziękuję Ci za to! Doprowadzało mnie do szału.
hackel
9

Jak już wspomniano w poprzedniej odpowiedzi , sytuacja ta może wynikać z problemów z zakończeniem linii (CR / LF vs. LF). Rozwiązałem ten problem (pod Git w wersji 2.22.0) za pomocą tego polecenia:

git add --renormalize .

Zgodnie z instrukcją:

       --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
źródło
To nowa najlepsza odpowiedź.
PHPst
5

Krótka odpowiedź

Bieganie git add czasami pomaga.

Przykład

Status Git pokazuje zmienione pliki, a git diff nic nie pokazuje ...

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

... uruchomienie git add rozwiązuje tę niespójność.

> git add
> git status
On branch master
nothing to commit, working directory clean
> 
Shaun Luttin
źródło
2
To brzmi dla mnie jak
``
@einjohn Jak myślisz, jaka jest choroba w tym przypadku?
Shaun Luttin
1
Choroba może mieć kilka przyczyn. Jak wspominali inni, może to być problem z uprawnieniami lub coś z zakończeniami linii. Mogą to być również zmiany już zainscenizowane. Jednak ta ostatnia możliwość nie pasuje do twojego przykładu. Niemniej jednak dzięki rozwiązaniu nie poznasz przyczyny (choroby), po prostu wyeliminujesz problem (pozornie błędny pusty diff (objawy)). Żeby było jasne: nie mówię, że to złe rozwiązanie. Może komuś pomóc, jeśli po prostu chce, aby problem zniknął. ... mam nadzieję, że rzuciłem trochę światła na moją metaferę choroby. :)
einjohn
@einjohn Wygląda na to, że przez większość czasu są to zakończenia linii. Wydaje się statusi diffmają różne sposoby radzenia sobie z nimi.
Shaun Luttin
5

Natknąłem się na ten problem. Moja sprawa była podobna do tej LESSkwestii pisał przez rcwxok .

W moim przypadku ustawiłem PAGERzmienną środowiskową naPAGER='less -RSF' .

Jednak w przeciwieństwie do poprzednich odpowiedzi, nie chciałem usuwać tej -Fopcji, ponieważ wyraźnie ją tam umieściłem, mając nadzieję, że nie pokaże różnicy wless jeśli jest krótsza niż ekranowa.

Aby uzyskać pożądany efekt, zamiast usuwania -F, dodałem -X: PAGER='less -RSFX'. To zarówno rozwiązało git diffproblem, jak i dodatkowo zapobiega wyświetlaniu krótkich różnic z less.

avivr
źródło
Kapitalizacja wydaje się dziwna. Czy masz na myśli „mniej -RSFX” zamiast „MNIEJ -RSFX”? Czy opcje są właściwe?
StackzOfZtuff
1
Tak, dzięki, to był błąd. Nie wiem, jak to się stało. Teraz naprawione.
avivr
3

Właśnie uruchomiłem podobny problem. git diff filenic nie pokazało, ponieważ dodałem plik do indeksu Gita z częścią jego nazwy wielkimi literami:GeoJSONContainer.js .

Potem zmieniłem nazwę na GeoJsonContainer.jsi zmiany przestały być śledzone. git diff GeoJsonContainer.jsnic nie pokazywał. Musiałem usunąć plik z indeksu za pomocą flagi siły i dodać plik ponownie:

git rm -f GeoJSONContainer.js
git add GeoJSONContainer.js
Alexandr Lazarev
źródło
2

Tak naprawdę nie zadałeś prawdziwego pytania, ale ponieważ jest to ogólny przypadek użycia, którego używam dość często, oto co robię. Możesz spróbować samemu i sprawdzić, czy błąd nadal występuje.

Moje założenie dotyczące twojego przypadku użycia:

Masz istniejący katalog zawierający pliki i katalogi, a teraz chcesz go przekonwertować na repozytorium Git, które jest sklonowane z innego miejsca bez zmiany jakichkolwiek danych w twoim bieżącym katalogu.

Są naprawdę dwa sposoby.

Clone repo - mv .git- git reset --hard

Ta metoda jest tym, co zrobiłeś - aby sklonować istniejące repozytorium do pustego katalogu, a następnie przenieść .gitkatalog do katalogu docelowego. Aby działać bez problemów, zwykle wymaga to uruchomienia

git reset --hard

Jednak zmieniłoby to stan plików w bieżącym katalogu. Możesz wypróbować to na pełnej kopii / rsync swojego katalogu i przestudiować, jakie zmiany. Przynajmniej później nie powinieneś już widzieć rozbieżności między git loga status.

Zainicjuj nowe repozytorium - wskaż początek

Drugi jest mniej niepokojący: dotrzyj cddo celu i rozpocznij nowe repozytorium z

git init

Następnie mówisz temu nowemu repozytorium, że ma przodka w innym miejscu:

git remote add origin original_git_repo_path

Wtedy bezpiecznie

git fetch origin master

kopiować dane bez zmiany plików lokalnych. Teraz wszystko powinno być dobrze.

Zawsze zalecam drugi sposób, aby być mniej podatnym na błędy.

cfi
źródło
Wydaje się, że sugerujesz, że jest to błąd git . Ok, mogłoby być. Nadal zakładałem, że brakuje mi odpowiedniego zrozumienia gita, bo nie jestem tak mądry jak Linus ;-)
towi
@towi: Nie, nie sugeruję, że jest to błąd git, ani nie sugeruję czegoś przeciwnego. Nie znam wewnętrznych elementów gita. Zgodnie z ogólną zasadą, przenosząc .gitfoldery do innych obszarów roboczych, potencjalnie naruszamy założenia git. Jeśli skutkuje to nieobliczalnym zachowaniem, nie możemy winić gita, musimy obwiniać siebie za granie z gitem. git zapewnia środki, aby to naprawić, np reset --hard. Po prostu nie tego chcemy. To jest dokładnie powód, dla którego ta init/remote adddroga jest zalecana i wszystko jest w porządku.
cfi,
@towi i Oliver P: Rozumiem, że chciałbyś, aby Twój konkretny przypadek błędu został rozwiązany, ale czasami zaleca się po prostu przestrzeganie ogólnych zaleceń - zwłaszcza jeśli idealnie pasują do Twojego przypadku użycia. Nie ma też utraty danych. A remote addsposób robienia rzeczy nadal można zastosować do
zepsutej
1
Głos „przeciw” bez komentarza nie pomaga poprawić tej odpowiedzi ani całej witryny. Ktokolwiek zagłosuje przeciw, zostaw komentarz, aby problem mógł zostać rozwiązany.
cfi
1

Ponownie natknąłem się na ten problem. Ale tym razem stało się to z innego powodu. Skopiowałem pliki do repozytorium, aby nadpisać poprzednie wersje. Teraz widzę, że pliki są zmodyfikowane, ale diff nie zwraca różnic.

Na przykład mam plik mainpage.xaml. W Eksploratorze plików wkleiłem nowy plik mainpage.xaml na ten w moim obecnym repozytorium. Wykonałem pracę na innym komputerze i właśnie wkleiłem plik tutaj.
git pokazuje zmodyfikowane

Plik pokazuje zmodyfikowane, ale kiedy uruchomię git diff, nie pokaże zmian. Dzieje się tak prawdopodobnie dlatego, że informacje o pliku w pliku uległy zmianie i git wie, że tak naprawdę nie jest to ten sam plik. Ciekawy.

git diff nic nie pokazuje

Możesz zobaczyć, że kiedy uruchamiam diff na pliku, nic nie pokazuje, po prostu zwraca znak zachęty.

raddevus
źródło
1

Miałem ten sam problem opisany w następujący sposób: Jeśli wpisałem

$ git diff

Git po prostu powrócił do monitu bez żadnego błędu.

Jeśli wpisałem

$ git diff <filename>

Git po prostu powrócił do monitu bez żadnego błędu.

W końcu, czytając wokół, zauważyłem, że git difffaktycznie wywołujemingw64\bin\diff.exe do wykonania pracy.

Oto oferta. Używam systemu Windows i zainstalowałem inne narzędzie Bash i zmieniło moją ścieżkę, więc nie wskazuje już na mój mingw64 \ bin .

Więc jeśli wpiszesz:

git diff

i po prostu powraca do monitu, że możesz mieć ten problem.

Rzeczywisty plik diff.exe, który jest uruchamiany, gitznajduje się w katalogu mingw64 \ bin

Wreszcie, aby to naprawić, skopiowałem plik mingw64\bin katalog do lokalizacji, w której szukał go Git. Próbowałem i nadal nie działało.

Następnie zamknąłem okno Git Bash i otworzyłem je ponownie, przeszedłem do tego samego repozytorium, które ulegało awarii i teraz działa.

raddevus
źródło