Moduły podrzędne: podstawowa koncepcja, przepływy pracy i porady
Nicola Paolucci
Developer Advocate
Wykorzystanie modułów podrzędnych w ramach prac programistycznych w Git pozwala na włączenie innych projektów do bazy kodu w taki sposób, że ich historia jest przechowywana oddzielnie, ale zsynchronizowana z Twoją. Jest to wygodna metoda rozwiązywania problemów z bibliotekami i zależnościami dostawców. Jak zwykle w przypadku git
to podejście wymaga trochę nauki, zanim będzie można je sprawnie stosować. Dostępne są już dobre i szczegółowe informacje na temat modułów podrzędnych
, więc nie będę ich tutaj powtarzać. Chcę jedynie podzielić się kilkoma interesującymi faktami, które pomogą optymalnie korzystać z tej funkcji.
Spis treści
materiały pokrewne
Jak przenieść pełne repozytorium Git
POZNAJ ROZWIĄZANIE
Poznaj środowisko Git z rozwiązaniem Bitbucket Cloud
Podstawowa koncepcja
Na początek pozwólcie, że objaśnię krótko podstawową koncepcję funkcjonowania modułów podrzędnych, która ułatwi pracę z nimi.
Moduły podrzędne są śledzone przez konkretny commit wskazany w projekcie nadrzędnym, a nie gałąź, referencję lub dowolne inne odniesienie symboliczne.
Nigdy nie są aktualizowane automatycznie wraz z aktualizacją repozytorium wskazanego przez moduł podrzędny, tylko wówczas, gdy aktualizowany jest sam projekt nadrzędny. Jak wskazano wyraźnie we wspomnianym wcześniej rozdziale książki Pro Git:
Gdy wprowadzasz zmiany i zatwierdzasz je w tym katalogu podrzędnym [submodule], projekt nadrzędny zauważa, że wskaźnik HEAD uległ tam zmianie i rejestruje dokładny commit, nad którym aktualnie pracujesz. Dzięki temu, gdy inni sklonują ten projekt, mogą dokładnie odtworzyć środowisko.
Lub innymi słowy:
[...] moduły podrzędne Git [...] są statyczne. Bardzo statyczne. Śledzisz konkretne commity, korzystając z modułów podrzędnych Git, a nie gałęzi, referencji czy pojedynczego commita. Jeśli dodasz commity do modułu podrzędnego, projekt nadrzędny nie będzie o tym wiedział. Jeśli wprowadzisz wiele podziałów modułu, moduły podrzędne Git nie będą zwracać na to uwagi. Masz jedno repozytorium zdalne i wskazujesz na pojedynczy commit. Do momentu aktualizacji projektu nadrzędnego nic się nie zmienia.
Możliwe przepływy pracy
Pamiętając o tej kluczowej koncepcji i mając ją na uwadze, możesz uzmysłowić sobie, że funkcja submodule
sprawdza się dobrze w niektórych przepływach pracy, a w innych jest mniej optymalny. Istnieją co najmniej trzy scenariusze, w których moduły podrzędne są dobrym wyborem:
-
Gdy komponent lub projekt podrzędny zmieniają się zbyt szybko lub nadchodzące zmiany spowodują uszkodzenie interfejsu API, możesz dla bezpieczeństwa zablokować kod na konkretnym commicie.
-
Gdy masz komponent, który nie jest aktualizowany zbyt często, a chcesz go śledzić jako zależność dostawcy. Sam robię tak na przykład ze swoimi wtyczkami vim.
-
Gdy delegujesz fragment projektu do innej osoby i chcesz zintegrować wykonaną przez nią pracę w konkretnym czasie lub wydaniu. Także tutaj ten sposób sprawdza się wówczas, gdy aktualizacje nie są zbyt częste.
Podziękowania dla fincha za dobrze wyjaśnione scenariusze.
Garść przydatnych porad
Infrastruktura modułów podrzędnych daje wiele możliwości i pozwala na przydatne rozdzielanie i integrowanie baz kodu. Istnieją jednak proste operacje, którym nie towarzyszy usprawniona procedura ani zaawansowana obsługa interfejsu użytkownika wiersza polecenia.
Jeśli korzystasz z modułów podrzędnych Git w swoim projekcie, na pewno zdarzyło lub zdarzy Ci się na nie natknąć. Wówczas trzeba będzie znaleźć rozwiązanie. A później znowu i znowu. Zaoszczędzę Ci poszukiwań: dodaj tę stronę do Instapaper, Evernote lub oznacz ją starą, dobrą zakładką (:D:D), a na chwilę będziesz mieć spokój.
Chcę tutaj omówić następujące tematy:
Jak zastąpić moduł podrzędny Git własnym podziałem?
To bardzo często używany przepływ pracy: zaczynasz korzystać z projektu innej osoby jako modułu podrzędnego, ale po jakimś czasie dostrzegasz potrzebę jego dostosowania do własnych potrzeb, chcesz więc utworzyć podział projektu i zastąpić moduł podrzędny własnym podziałem. Jak to zrobić?
Moduły podrzędne są przechowywane w pliku .gitmodules
:
$ cat .gitmodules [submodule "ext/google-maps"] path = ext/google-maps url = git://git.naquadah.org/google-maps.git
Wystarczy, że zmodyfikujesz adres URL w edytorze tekstu, a potem wykonasz następujące polecenie:
$ git submodule sync
Spowoduje to aktualizację pliku .git/config
, który zawiera kopię listy tego modułu podrzędnego (możesz również edytować odpowiednią sekcję [submodule]
pliku .git/config
ręcznie).
Jak usunąć moduł podrzędny?
Jest to stosunkowo częsta potrzeba, jednak sama procedura jest nieco zawiła. Aby usunąć moduł podrzędny:
1. Usuń odpowiedni wiersz z pliku .gitmodules
.
2. Usuń odpowiednią sekcję z pliku .git/config
.
3. Uruchom polecenie git rm --cached path_to_submodule
(bez ukośnika na końcu).
4. Zatwierdź i usuń nieśledzone już pliki modułów podrzędnych.
Jak ponownie zintegrować moduł podrzędny ze swoim projektem?
Lub, innymi słowy, jak sprawić, aby moduł podrzędny Git przestał być modułem podrzędnym? Jeśli chcesz jedynie umieścić kod z modułu podrzędnego w głównym repozytorium, wystarczy, że usuniesz moduł podrzędny, a następnie ponownie dodasz pliki do głównego repozytorium:
1. Usuń z indeksu referencję do modułu podrzędnego, ale zachowaj pliki:
git rm --cached submodule_path (no trailing slash)
2. Usuń plik .gitmodules lub, jeśli masz więcej niż jeden moduł podrzędny, zmodyfikuj ten plik, usuwając moduł podrzędny z listy:
git rm .gitmodules
3. Usuń folder metadanych .git (najpierw wykonaj jego kopię zapasową):
rm -rf submodule_path/.git
4. Dodaj moduł podrzędny (submodule
) do indeksu głównego repozytorium:
git add submodule_path git commit -m "remove submodule"
UWAGA: Opisana powyżej procedura niszczy historię modułu podrzędnego. Jeśli chcesz zachować odpowiednią historię swoich modułów podrzędnych, musisz przejść przez wymyślną procedurę „scalania”. Więcej szczegółów znajdziesz w tym wyczerpującym opracowaniu w witrynie Stack Overflow.
Jak zignorować zmiany w modułach podrzędnych?
Czasami Twoje moduły podrzędne submodule
mogą same z siebie przyjąć status dirty
. Jeśli na przykład korzystasz z opcji submodule
w Git do śledzenia swoich wtyczek vim, mogą one generować lub modyfikować pliki lokalne, takie jak helptags
. Niestety polecenie git status zacznie Cię irytować komunikatami o tych zmianach, nawet jeśli nie będziesz się nimi wcale interesować i nie będziesz chcieć ich zatwierdzać.
Rozwiązanie jest bardzo proste. Otwórz plik .gitmodules
w katalogu głównym Twojego repozytorium i dla każdego modułu podrzędnego, który chcesz zignorować, dodaj zapis ignore = dirty
, jak w następującym przykładzie:
[submodule ".vim/bundle/msanders-snipmate"] path = .vim/bundle/msanders-snipmate url = git://github.com/msanders/snipmate.vim.git ignore = dirty
Podziękowania dla Nilsa za to świetne objaśnienie.
Strefa zagrożenia! Pułapki w interakcjach ze zdalnymi repozytoriami
Jak wspomniano w samouczku na temat modułów podrzędnych Git w witrynie kernel.org, przy interakcjach ze zdalnymi repozytoriami trzeba wziąć pod uwagę kilka ważnych kwestii.
Po pierwsze zmiany w module podrzędnym należy publikować zawsze przed opublikowaniem zmiany w projekcie nadrzędnym, który się do niego odnosi. Ma to krytyczne znaczenie, ponieważ może utrudniać innym klonowanie repozytorium.
Po drugie zawsze zależy pamiętać o zatwierdzeniu wszystkich zmian przed wykonaniem polecenia git submodule update
, ponieważ wszelkie zmiany zostaną nadpisane.
Wnioski
Wiedząc o tym, będziesz w stanie poradzić sobie z wieloma typowymi, powtarzającymi się przepływami pracy występującymi podczas korzystania z modułów podrzędnych. W kolejnym wpisie opowiem o alternatywach dla operacji git submodule
.
Obserwuj mnie (@durdn) i niesamowity zespół @Bitbucket, aby otrzymywać więcej informacji o DVCS.
Udostępnij ten artykuł
Następny temat
Zalecane lektury
Dodaj te zasoby do zakładek, aby dowiedzieć się więcej na temat rodzajów zespołów DevOps lub otrzymywać aktualności na temat metodyki DevOps w Atlassian.