Git diff mówi, że podprojekt jest brudny

227

Właśnie uruchomiłem git diff i otrzymuję następujący wynik dla wszystkich moich około 10 podmodułów

diff --git a/.vim/bundle/bufexplorer b/.vim/bundle/bufexplorer
--- a/.vim/bundle/bufexplorer
+++ b/.vim/bundle/bufexplorer
@@ -1 +1 @@
-Subproject commit 8c75e65b647238febd0257658b150f717a136359
+Subproject commit 8c75e65b647238febd0257658b150f717a136359-dirty

Co to znaczy? Jak to naprawić?

mrwooster
źródło

Odpowiedzi:

268

Jak wspomniano w blogu Marka Longaira Git Submodules Explained ,

Wersje 1.7.0 i nowsze programu git zawierają irytującą zmianę w zachowaniu podmodułu git.
Podmoduły są teraz uważane za brudne, jeśli zawierają zmodyfikowane pliki lub pliki nieśledzone , podczas gdy poprzednio miało to miejsce tylko wtedy, gdy HEAD w podmodule wskazywał na niewłaściwe zatwierdzenie.

Znaczenie znaku plus ( +) w wyjściu podmodułu git zmieniło się, a kiedy pierwszy raz się z tym spotkasz, zajmie trochę czasu, aby dowiedzieć się, co się dzieje, na przykład przeglądając dzienniki zmian lub używając git bisect na git .git, aby znaleźć zmianę. Byłoby znacznie milsze dla użytkowników, aby wprowadzić inny symbol „w określonej wersji, ale brudny”.

Możesz to naprawić poprzez:

  • popełnianie lub cofanie zmian / zmian w każdym z twoich submodułów, przed powrotem do repozytorium nadrzędnego (gdzie diff nie powinien już zgłaszać „brudnych” plików). Aby cofnąć wszystkie zmiany w twoim module podrzędnym, po prostu cdw katalogu głównym swojego modułu podrzędnego i wykonajgit checkout .

    dotnetCarpenter komentuje , że możesz:git submodule foreach --recursive git checkout .

  • lub dodaj --ignore-submodulesdo swojego git diff, aby tymczasowo zignorować te „brudne” submoduły.

Nowości w wersji Git 1.7.2

Jak komentuje Noam poniżej , w tym pytaniu wspomina się, że od wersji git 1.7.2 możesz zignorować brudne submoduły za pomocą:

git status --ignore-submodules=dirty
VonC
źródło
2
Warto również wiedzieć: nadal możesz wykonywać git commit -abez dodawania tych zmian. Chociaż są oznaczone z Mprzodu, nie trafią do twojego zatwierdzenia.
gitaarik
1
Dla mnie musiałem wejść do każdego brudnego submodułu i uruchomić git clean -id.
GDP2
1
@ GDP2, którą możesz przekazać w jednym wierszu, za pomocą git submodule foreach --recursive git clean -id(najpierw do przetestowania w kopii zapasowej;))
VonC
1
W przypadku, gdy widziałem to w niewytłumaczalny sposób, działo się tak, że miałem nieśledzone pliki, których nie było w podmodule .gitignore. Dodanie ich tam lub do mojej globalnej listy ignorowanych naprawiło rzeczy.
Ben
21

Również usunięcie submodułu, a następnie uruchomienie git submodule initi git submodule updateoczywiście załatwi sprawę, ale nie zawsze może być odpowiednie lub możliwe.

użytkownik1178907
źródło
1
Działa to dla mnie, gdy przekonwertowałem niektóre istniejące foldery na submoduły, a następnie wciągnąłem na inną maszynę, która wciąż miała stare foldery.
Roger Lipscombe
18

Aby zignorować wszystkie nieśledzone pliki w dowolnym podmodule, użyj następującego polecenia, aby zignorować te zmiany.

git config --global diff.ignoreSubmodules dirty

Doda to następującą opcję konfiguracji do lokalnej konfiguracji git:

[diff]
  ignoreSubmodules = dirty

Więcej informacji można znaleźć tutaj

Devpool
źródło
16

EDYCJA : Ta odpowiedź (i większość innych) jest nieaktualna; zamiast tego zobacz odpowiedź Devpoola .


Początkowo nie było żadnych opcji konfiguracyjnych, aby „ git diff --ignore-submodules” i „ git status --ignore-submodules” globalny domyślny (ale patrz też Ustawienie domyślne flagi na git poleceń ). Alternatywą jest ustawienie domyślnej ignoreopcji konfiguracji dla każdego podmodułu, który chcesz zignorować (dla obu git diffi git status), albo w .git/configpliku (tylko lokalnie), albo .gitmodules(będzie wersjonowany przez git). Na przykład:

[submodule "foobar"]
    url = [email protected]:foo/bar.git
    ignore = untracked

ignore = untrackedaby zignorować tylko nieśledzone pliki, ignore = dirtyaby również zignorować zmodyfikowane pliki i ignore = allzignorować również zatwierdzenia. Najwyraźniej nie ma sposobu, aby zastosować go do wszystkich podmodułów.

Ralph Versteegen
źródło
13

Dzieje się tak, ponieważ wskaźnik, który masz dla submodułu, nie jest tym, co faktycznie znajduje się w katalogu submodułu. Aby to naprawić, musisz uruchomić git submodule updateponownie:

Robin Ren
źródło
9
git submodule foreach --recursive git checkout .

To nie pomogło mi, ale dało mi listę plików (w moim przypadku tylko jeden), które zostały zmienione w submodule (bez mojej pomocy).

Mogłem więc przejść do podmodułu, a status git pokazał mi, że mój HEAD został odłączony -> master git checkout, status git, aby zobaczyć zmodyfikowany plik jeszcze raz, git checkout> nazwa pliku <, git pull i wszystko w porządku.

Tylko trochę
źródło
9

W końcu usunąłem katalog submodułu i zainicjowałem go jeszcze raz

cd my-submodule
git push
cd ../
rm -rf my-submodule
git submodule init
git submodule update
Szymon Wygnański
źródło
4
Wolałbym zrozumieć, co się stało, ale to była jedyna rzecz, która zadziałała dla mnie ...
smilebomb
6

Podmoduł może zostać oznaczony jako brudny, jeśli włączone są ustawienia trybu pliku i zmieniono uprawnienia do plików w poddrzewie podmodułu.

Aby wyłączyć tryb pliku w submodule, możesz edytować /.git/modules/path/to/your/submodule/config i dodać

[core]
  filemode = false

Jeśli chcesz zignorować wszystkie brudne stany, możesz ustawić ignore = dirtywłaściwość w pliku /.gitmodules , ale myślę, że lepiej jest wyłączać tylko tryb pliku.

dryobs
źródło