Aktualizacja podmodułu Git

242

Nie jestem pewien, co oznacza (z dokumentacji aktualizacji modułu podrzędnego Git ):

... sprawi, że podmoduły HEAD zostaną odłączone, chyba że --rebaselub --mergezostanie określony ...

Jak --rebase/ --mergezmienia rzeczy?

Moim głównym przykładem użycia jest posiadanie kilku centralnych repozytoriów, które za pośrednictwem submodułów będę osadzał w innych repozytoriach. Chciałbym móc ulepszyć te centralne repozytoria, albo bezpośrednio w ich oryginalnej lokalizacji, albo z ich wbudowanych repozytoriów (tych, które używają ich przez submoduł).

  • Czy w ramach tych podmodułów mogę tworzyć gałęzie / modyfikacje i używać push / pull tak jak w zwykłych repozytoriach, czy też jest coś, na co należy uważać?
  • Jak mogę przejść do zatwierdzonego modułu podrzędnego z powiedzmy (otagowany) 1.0 do 1.1 (nawet jeśli nagłówek oryginalnego repozytorium ma już wersję 2.0) lub wybrać, który z zatwierdzonych gałęzi w ogóle jest używany?
Głęboki błękit
źródło
Na temat „odłączonej głowy” patrz także stackoverflow.com/questions/964876/head-and-orighead-in-git i stackoverflow.com/questions/237408/ ... jako praktyczny przykład (niezwiązany z submodułami, ale nadal )
VonC
„nie można modyfikować zawartości submodułu z głównego projektu”: tak, prawda. A ja zredagowałem swoją odpowiedź, aby rzucić nieco światła na tę pozorną sprzeczność (niezmodyfikowalny submoduł, który wciąż można modyfikować z głównego repozytorium projektu!)
VonC

Odpowiedzi:

304

Ta strona GitPro ładnie podsumowuje konsekwencje aktualizacji podmodułu git

Po uruchomieniu git submodule updatesprawdza konkretną wersję projektu, ale nie w ramach oddziału. Nazywa się to posiadaniem odłączonej głowy - oznacza to, że plik HEAD wskazuje bezpośrednio na zatwierdzenie, a nie na symboliczne odniesienie.
Problem polega na tym, że generalnie nie chcesz pracować w odłączonym środowisku głowy, ponieważ łatwo jest utracić zmiany .
Jeśli wykonasz początkową aktualizację podmodułu, zatwierdź w tym katalogu podmodułów bez tworzenia gałęzi, w której chcesz pracować, a następnie ponownie uruchom aktualizację podmodułu git z superprojektu bez zatwierdzania w międzyczasie, Git nadpisze twoje zmiany bez powiadomienia. Technicznie nie stracisz pracy, ale nie będziesz mieć do niej gałęzi, więc będzie to trochę trudne do odzyskania.


Uwaga marzec 2013:

Jak wspomniano w „ Śledzenie podmodułu git najnowsze ”, teraz podmoduł (git1.8.2) może śledzić gałąź.

# add submodule to track master branch
git submodule add -b master [URL to Git repo];

# update your submodule
git submodule update --remote 
# or (with rebase)
git submodule update --rebase --remote

Zobacz „ git submodule update --remotevsgit pull ”.

MindTooth „s odpowiedź zilustrować ręczną aktualizację (bez lokalnej konfiguracji):

git submodule -q foreach git pull -q origin master

W obu przypadkach spowoduje to zmianę odniesień do podmodułów ( gitlink , specjalny wpis w nadrzędnym indeksie repo ) i konieczne będzie dodanie, zatwierdzenie i przekazanie wspomnianych referencji z głównego repozytorium.
Następnym razem, gdy sklonujesz to repozytorium nadrzędne, zapełni ono podmoduły, aby odzwierciedlić te nowe odwołania SHA1.

Pozostała część tej odpowiedzi szczegółowo opisuje klasyczną funkcję submodułu (odniesienie do ustalonego zatwierdzenia, które jest najważniejszym punktem koncepcji submodułu).


Aby uniknąć tego problemu, utwórz gałąź podczas pracy w katalogu submodułów z git checkout -b work lub czymś równoważnym. Gdy wykonasz aktualizację podmodułu po raz drugi, nadal będzie ona cofać twoją pracę, ale przynajmniej masz wskaźnik, do którego możesz wrócić.

Przełączanie gałęzi z submodułami może być również trudne. Jeśli utworzysz nową gałąź, dodaj tam moduł podrzędny, a następnie przełącz się z powrotem do gałęzi bez tego modułu, nadal masz katalog modułów podrzędnych jako katalog bez śledzenia:


Aby odpowiedzieć na twoje pytania:

czy mogę tworzyć gałęzie / modyfikacje i używać push / pull tak, jak w przypadku zwykłych repozytoriów, czy też jest coś, na co należy uważać?

Możesz utworzyć gałąź i modyfikacje push.

OSTRZEŻENIE (z samouczka Git Submodule ): Zawsze publikuj (wypychaj) zmianę podmodułu przed publikowaniem (wypychaj) zmiany do superprojektu, który się do niej odwołuje. Jeśli zapomnisz opublikować zmianę submodułu, inni nie będą mogli sklonować repozytorium.

w jaki sposób miałbym przejść do zatwierdzonego podmodułu, zatwierdzając od powiedzmy (otagowano) 1.0 do 1.1 (nawet jeśli nagłówek oryginalnego repo jest już w wersji 2.0)

Strona „ Zrozumienie submodułów ” może pomóc

Podmoduły Git są implementowane przy użyciu dwóch ruchomych części:

  • .gitmodulesplik i
  • specjalny rodzaj drzewa.

Te razem triangulują konkretną wersję konkretnego repozytorium, która jest wyewidencjonowana w określonej lokalizacji w twoim projekcie.


Ze strony podmodułu git

nie można modyfikować zawartości submodułu z poziomu głównego projektu

100% poprawność: nie można modyfikować submodułu, odwołać się tylko do jednego z jego zatwierdzeń.

Dlatego modyfikując submoduł z głównego projektu, wykonujesz:

  • trzeba zatwierdzić i pchnąć w podmodule (do modułu nadrzędnego), oraz
  • następnie przejdź do głównego projektu i ponownie zatwierdzaj (aby ten główny projekt odwoływał się do nowo zatwierdzonego modułu podrzędnego, który właśnie utworzyłeś i przekazałeś)

Podmoduł umożliwia opracowanie podejścia opartego na komponentach , gdzie główny projekt odnosi się tylko do określonych zatwierdzeń innych komponentów (tutaj „inne repozytoria Git zadeklarowane jako podmoduły”).

Podmoduł jest znacznikiem (zatwierdzeniem) w innym repozytorium Git, które nie jest związane głównym cyklem rozwoju projektu: to („inne” repozytorium Git) może ewoluować niezależnie.
Do głównego projektu należy wybranie z tego drugiego repozytorium dowolnego potrzebnego zatwierdzenia.

Jeśli jednak chcesz, dla wygody , zmodyfikować jedną z tych podmodułów bezpośrednio z głównego projektu, Git pozwala to zrobić, pod warunkiem, że najpierw opublikujesz te modyfikacje podmodułu w oryginalnym repozytorium Git, a następnie zatwierdzisz swój główny projekt, odnosząc się do nowa wersja wspomnianego modułem.

Ale główna idea pozostaje: odniesienie do konkretnych komponentów, które:

  • mają swój własny cykl życia
  • mają własny zestaw tagów
  • mają własny rozwój

Lista konkretnych zatwierdzeń, do których się odwołujesz w głównym projekcie, określa twoją konfigurację (na tym właśnie polega Zarządzanie konfiguracją , englobowanie zwykłego systemu kontroli wersji )

Jeśli komponent można naprawdę opracować w tym samym czasie, co główny projekt (ponieważ każda modyfikacja w głównym projekcie wymagałaby modyfikacji podkatalogu i odwrotnie), byłby to już „podmoduł”, ale scalanie poddrzewa (przedstawione również w pytaniu Przenoszenie starszej bazy kodu z CVS do repozytorium rozproszonego ), łącząc ze sobą historię dwóch repozytoriów Git.

Czy to pomaga zrozumieć prawdziwą naturę submodułów Git?

VonC
źródło
77
Łał. To długie wytłumaczenie czegoś, co jest zasadniczo tak proste, powinno wystarczyć, aby przestraszyć każdego nowo przybyłego do po prostu trzymania się swojego svn: zewnętrznych. ;-)
conny
2
@conny: ale, jak szczegółowo opisałem w „ Dlaczego submoduły git są niezgodne z zewnętrznymi svn? ”, submoduły różnią się zasadniczo i nie są kompatybilne z svn:externals.
VonC
1
Niestety, aby odpowiedzieć na moje pytanie, zbieram cd'ing do submodułu i git kasuje sha, albo git pull / fetch zrobi dobrze. Następnie zatwierdzanie aktualizacji w lokalnym repozytorium.
Henrik,
2
@hced: Możesz także trafić wszystkie podmoduły jednocześnie, używającgit submodule foreach
Dav Clark
1
.. wciąż nie rozumiem. czy gdzieś w Internecie jest łatwiejsze wyjaśnienie?
eugene
135

Aby zaktualizować każdy podmoduł, możesz wywołać następujące polecenie (w katalogu głównym repozytorium):

git submodule -q foreach git pull -q origin master

Możesz usunąć opcję -q , aby śledzić cały proces.

MindTooth
źródło
15
Jeśli po prostu uruchomisz git submodule update --init --recursivez katalogu głównego, pobierze je wszystkie rekurencyjnie i zainicjuje je, jeśli jeszcze nie są.
Sam Soffes
10
@SamSoffes To służy całkowicie innemu celowi. Aktualizacja submodułów sprawdzi submoduły przy zatwierdzonym przez nich aktualnie zatwierdzeniu (niekoniecznie ostatnim zatwierdzeniu). Rozwiązanie w powyższej odpowiedzi aktualizuje zatwierdzenie każdego podmodułu do najnowszego HEAD od origin / master.
indragie
7
Moja nowa metoda:git submodule update --rebase --remote
MindTooth
19

Aby rozwiązać opcję --rebasevs.--merge

Powiedzmy, że masz super repozytorium A i submoduł B i chcesz popracować w submodule B. Odrobiłeś pracę domową i wiesz, że po wywołaniu

git submodule update

jesteś w stanie bez HEAD, więc trudno jest wrócić do wszelkich zatwierdzeń, które wykonasz w tym momencie. Rozpocząłeś pracę nad nowym oddziałem w podmodule B

cd B
git checkout -b bestIdeaForBEver
<do work>

Tymczasem ktoś inny w projekcie A zdecydował, że najnowsza i najlepsza wersja B jest naprawdę tym, na co zasługuje A. Z przyzwyczajenia scalasz ostatnie zmiany i aktualizujesz swoje podmoduły.

<in A>
git merge develop
git submodule update

Och nie! Znowu jesteś w stanie bezgłowym, prawdopodobnie dlatego, że B wskazuje teraz SHA związane z nową wskazówką B lub innym zatwierdzeniem. Gdybyś tylko miał:

git merge develop
git submodule update --rebase

Fast-forwarded bestIdeaForBEver to b798edfdsf1191f8b140ea325685c4da19a9d437.
Submodule path 'B': rebased into 'b798ecsdf71191f8b140ea325685c4da19a9d437'

Teraz ten najlepszy pomysł na B został oparty na nowym zatwierdzeniu, a co ważniejsze, nadal jesteś w swojej gałęzi rozwoju dla B, a nie w stanie bezgłowym!

( --mergeScalą zmiany z beforeUpdateSHA do afterUpdateSHA w działający oddział, w przeciwieństwie do przeniesienia zmian na afterUpdateSHA.)

robinspb
źródło
7

Git 1.8.2 oferuje nową opcję --remote, która umożliwi dokładnie takie zachowanie. Bieganie

git submodule update --rebase --remote

pobierze najnowsze zmiany z wyższego poziomu w każdym podmodule, wyłączy je i sprawdzi najnowszą wersję tego podmodułu. Zgodnie z dokumentacją :

--zdalny

Ta opcja jest ważna tylko dla polecenia aktualizacji. Zamiast używać nagranego SHA-1 superprojektu do aktualizacji submodułu, użyj statusu gałęzi zdalnego śledzenia submodułu.

Jest to równoważne z uruchomieniem git pullw każdym podmodule, co jest generalnie dokładnie tym, czego chcesz.

(Zostało to skopiowane z tej odpowiedzi ).

Iulian Onofrei
źródło
Jeśli zdecydujesz się odpowiedzieć na starsze pytanie, które ma dobrze ustalone i poprawne odpowiedzi, dodanie nowej odpowiedzi późno w ciągu dnia może nie przynieść ci uznania. Jeśli masz jakieś nowe, charakterystyczne informacje lub jesteś przekonany, że wszystkie inne odpowiedzi są błędne, dodaj nową odpowiedź, ale „jeszcze jedna odpowiedź”, podając tę ​​samą podstawową informację długo po wygraniu pytania, zwykle wygrywa ” zarobię ci dużo kredytu. Nie ma wyjaśnienia, co to robi - nawet łącza do dokumentacji zewnętrznej (co nie byłoby wystarczające).
Jonathan Leffler,
2
To nie jest „kolejna odpowiedź”, ponieważ ŻADNA inna odpowiedź nie ma tego polecenia (udowodnij, że się mylę). Inne odpowiedzi nie działały dla mnie, ten komentarz zadziałał , więc postanowiłem opublikować je jako odpowiedź, jednocześnie uznając oryginalnego właściciela. Zastanów się więc nad usunięciem swojej opinii.
Iulian Onofrei,
Istnieje komentarz przez MindTooth od 2015 mówiąc to, co robią teraz. Nie podajesz żadnego wyjaśnienia, co to robi (chociaż wspominasz o MindTooth, ale nie ma prawdziwego wyjaśnienia, co masz na myśli mówiąc, że osadzanie adresów URL, tak jak w tym komentarzu, pomogłoby). Nie mówisz, dlaczego to dobry pomysł. Nie dajesz żadnych zastrzeżeń. Moim zdaniem nie jest to pomocna odpowiedź, ponieważ rodzi więcej pytań niż rozwiązuje.
Jonathan Leffler,
1
Rozumiałem przez to, że działa zamiast nie działać. Uwierzcie mi, gdyby więcej osób zobaczyło tę odpowiedź, byliby zadowoleni, ponieważ to działa . W przypadku takich rzeczy większość ludzi chce po prostu poznać polecenie aktualizujące podmoduł git, a nie sposób jego implementacji.
Iulian Onofrei,
Zredagowałem odpowiedź, aby udowodnić, że się mylisz, także stackoverflow.com/questions/1979167/git-submodule-update/… !!!
Iulian Onofrei,