Jak zrobić płytkie podmoduły git?

139

Czy można mieć płytkie podmoduły? Mam superprojekt z kilkoma modułami podrzędnymi, z których każdy ma długą historię, więc ciągnięcie całej tej historii jest niepotrzebnie duże.

Znalazłem tylko ten wątek bez odpowiedzi .

Czy powinienem po prostu zhakować git-submodule, aby to zaimplementować?

Mauricio Scheffer
źródło
1
git submodule add/update” może teraz sklonować repozytoria podmodułów płytko! Zobacz moją odpowiedź poniżej
VonC

Odpowiedzi:

133

Nowość w nadchodzącym git1.8.4 (lipiec 2013) :

git submodule update” może opcjonalnie sklonować repozytoria podmodułów płytko.

(I git 2.10 Q3 2016 pozwala to nagrać z git config -f .gitmodules submodule.<name>.shallow true.
Zobacz koniec tej odpowiedzi)

Zobacz commit 275cd184d52b5b81cb89e4ec33e540fb2ae61c1f :

Dodaj --depthopcję do poleceń dodawania i aktualizowania „git submodule”, która jest następnie przekazywana do polecenia clone. Jest to przydatne, gdy podmoduły są ogromne i nie interesuje Cię nic poza najnowszym zatwierdzeniem.

Dodano testy i wprowadzono pewne poprawki wcięć, aby były zgodne z resztą pliku testowego w sekcji „Aktualizacja modułu podrzędnego może obsługiwać dowiązania symboliczne w pwd”.

Podpisał: Fredrik Gustafsson <[email protected]>
Potwierdził: Jens Lehmann<[email protected]>

Oznacza to, że to działa:

git submodule add --depth 1 -- repository path
git submodule update --depth -- [<path>...]

Z:

--depth::

Ta opcja dotyczy poleceń addi update.
Utwórz „płytki” klon z historią skróconą do określonej liczby wersji.


atwyman dodaje w komentarzach :

O ile wiem, ta opcja nie jest użyteczna dla modułów podrzędnych, które nie śledzą masterzbyt dokładnie. Jeśli ustawisz głębokość 1, submodule updatemożesz odnieść sukces tylko wtedy, gdy żądane zatwierdzenie podmodułu jest najnowszym wzorcem. W przeciwnym razie otrzymasz „ fatal: reference is not a tree .

To prawda.
To znaczy do git 2.8 (marzec 2016). Z 2.8, submodule update --depthma jeszcze jedną szansę na sukces, nawet jeśli SHA1 jest bezpośrednio osiągalny z jednego ze zdalnych głowic repozytorium.

Zobacz commit fb43e31 (24 lutego 2016) autorstwa Stefana Bellera ( stefanbeller) .
Z pomocą: Junio ​​C Hamano ( gitster) .
(Scalone przez Junio ​​C Hamano - gitster- w zobowiązaniu 9671a76 , 26 lutego 2016 r.)

podmoduł: spróbuj mocniej pobrać potrzebny sha1 przez bezpośrednie pobranie sha1

Podczas przeglądania zmiany, która aktualizuje również moduł podrzędny w Gerrit, powszechną praktyką jest pobieranie i wybieranie poprawki lokalnie w celu jej przetestowania.
Jednak podczas testowania lokalnego „ git submodule update” może się nie powieść podczas pobierania prawidłowego modułu podrzędnego sha1, ponieważ odpowiednie zatwierdzenie w module podrzędnym nie jest jeszcze częścią historii projektu, ale także tylko proponowaną zmianą.

Jeśli $sha1nie było częścią domyślnego pobierania, próbujemy pobrać $sha1bezpośrednio . Jednak niektóre serwery nie obsługują bezpośredniego pobierania przez sha1, co prowadzi git-fetchdo szybkiej awarii.
Tutaj możemy zawieść siebie, ponieważ wciąż brakujący sha1 i tak doprowadziłby do niepowodzenia na późniejszym etapie kasy, więc niepowodzenie tutaj jest tak dobre, jak to tylko możliwe.


MVG wskazuje w komentarzach na popełnienie fb43e31 (git 2.9, luty 2016)

Wydawałoby mi się, że zatwierdzenie fb43e31 żąda brakującego zatwierdzenia przez identyfikator SHA1, więc ustawienia uploadpack.allowReachableSHA1InWanti uploadpack.allowTipSHA1InWantna serwerze prawdopodobnie wpłyną na to, czy to zadziała.
Napisałem dzisiaj post do listy git , wskazując, w jaki sposób użycie płytkich podmodułów może działać lepiej w niektórych sytuacjach, a mianowicie, jeśli zatwierdzenie jest również tagiem.
Poczekajmy i zobaczmy.

Myślę, że jest to powód, dla którego fb43e31 sprawił, że pobieranie dla określonego SHA1 było rezerwą po pobraniu dla domyślnej gałęzi.
Niemniej jednak, w przypadku „--depth 1” myślę, że rozsądne byłoby przerwanie wcześniejszej przerwy: jeśli żaden z wymienionych ref nie pasuje do żądanego, a zapytanie przez SHA1 nie jest obsługiwane przez serwer, to nie ma sensu pobieranie czegokolwiek, ponieważ w żaden sposób nie będziemy w stanie spełnić wymagań modułu podrzędnego.


Aktualizacja sierpień 2016 (3 lata później)

Dzięki Git 2.10 (III kwartał 2016 r.) Będziesz w stanie to zrobić

 git config -f .gitmodules submodule.<name>.shallow true

Zobacz „ Moduł podrzędny Git bez dodatkowej wagi ”, aby uzyskać więcej informacji.


Git 2.13 (Q2 2017) dodaje w zatwierdzeniu 8d3047c (19 kwietnia 2017) autorstwa Sebastiana Schubertha ( sschuberth) .
(Scalone przez Sebastiana Schubertha - sschuberth- w zobowiązaniu 8d3047c , 20 kwietnia 2017 r.)

klon tego submodułu zostanie wykonany jako płytki klon (z głębokością historii 1)

Jednak Ciro Santilli dodaje w komentarzach (i szczegółach w swojej odpowiedzi )

shallow = truena .gitmodulestylko wpływa na odniesienie śledzone przez szefa pilocie podczas używania --recurse-submodules, nawet jeśli cel popełnić jest wskazywany przez oddział, a nawet jeśli umieścić branch = mybranchna .gitmodulesjak dobrze.


Git 2.20 (Q4 2018) ulepsza obsługę modułu podrzędnego, który został zaktualizowany do odczytu z obiektu BLOB w HEAD:.gitmodulesprzypadku .gitmodulesbraku pliku w drzewie roboczym.

Zobacz commit 2b1257e , commit 76e9bdc (25 października 2018) i commit b5c259f , commit 23dd8f5 , commit b2faad4 , commit 2502ffc , commit 996df4d , commit d1b13df , commit 45f5ef3 , commit bcbc780 (05 Oct 2018) autor: Antonio Ospite ( ao2) .
(Scalone przez Junio ​​C Hamano - gitster- w zobowiązaniu abb4824 , 13 listopada 2018 r.)

submodule: obsługuje czytanie, .gitmodulesgdy nie ma go w drzewie roboczym

Jeśli .gitmodulesplik nie jest dostępny w drzewie roboczym, spróbuj użyć zawartości z indeksu iz bieżącej gałęzi.
Obejmuje to przypadek, gdy plik jest częścią repozytorium, ale z jakiegoś powodu nie jest wyewidencjonowany, na przykład z powodu rzadkiego pobierania.

To sprawia, że możliwe jest wykorzystanie przynajmniej „ git submodule” polecenia, które czytają ten gitmodulesplik konfiguracyjny bez pełnego wypełniania drzewa roboczą.

Zapis do .gitmodulesnadal będzie wymagał wyewidencjonowania pliku, więc sprawdź to przed wywołaniem config_set_in_gitmodules_file_gently.

Dodaj podobne sprawdzenie również, git-submodule.sh::cmd_add()aby przewidzieć ewentualne niepowodzenie git submodule addpolecenia „ ”, gdy .gitmodulesnie można go bezpiecznie zapisać; zapobiega to pozostawieniu przez polecenie repozytorium w stanie fałszywym (np. repozytorium modułu podrzędnego zostało sklonowane, ale .gitmodulesnie zostało zaktualizowane z powodu config_set_in_gitmodules_file_gentlyniepowodzenia).

Ponadto, ponieważ config_from_gitmodules()teraz uzyskuje dostęp do globalnej składnicy obiektów, konieczne jest zabezpieczenie wszystkich ścieżek kodu, które wywołują funkcję, przed równoczesnym dostępem do globalnej składnicy obiektów.
Obecnie dzieje się tak tylko w builtin/grep.c::grep_submodules(), więc wywołaj grep_read_lock()przed wywołaniem kodu obejmującego config_from_gitmodules().

UWAGA: istnieje jeden rzadki przypadek, w którym ta nowa funkcja nie działa jeszcze poprawnie: zagnieżdżone podmoduły bez .gitmodulesw ich drzewie roboczym.


Uwaga: Git 2.24 (Q4 2019) naprawia możliwy błąd segregacji podczas klonowania płytkiego podmodułu.

Zobacz commit ddb3c85 (30 września 2019) autorstwa Ali Utku Selen ( auselen) .
(Scalone przez Junio ​​C Hamano - gitster- w zatwierdzeniu 678a9ca , 09 października 2019)


Git 2.25 (Q1 2020), wyjaśnia git submodule updatedokumentację.

Zobacz commit f0e58b3 (24 listopada 2019) autorstwa Philippe Blaina ( phil-blain) .
(Scalone przez Junio ​​C Hamano - gitster- w zatwierdzeniu ef61045 , 05 grudnia 2019)

doc: wspomnij, że 'git submodule update' pobiera brakujące zatwierdzenia

Pomoc: Junio ​​C Hamano
Pomoc: Johannes Schindelin
Podpisał: Philippe Blain

' git submoduleupdate' pobierze nowe zatwierdzenia ze zdalnego submodułu, jeśli SHA-1 zapisany w superprojekcie nie zostanie znaleziony . Nie było to wspomniane w dokumentacji.


Ostrzeżenie: W Git 2.25 (Q1 2020) interakcja między „ git clone --recurse-submodules” a alternatywną składnicą obiektów była źle zaprojektowana.

Nauczono dokumentacji i kodu, aby przedstawiać bardziej jasne zalecenia, gdy użytkownicy widzą awarie.

Zobacz commit 4f3e57e , commit 10c64a0 (02 grudnia 2019) autorstwa Jonathan Tan ( jhowtan) .
(Scalone przez Junio ​​C Hamano - gitster- w zatwierdzeniu 5dd1d59 , 10 grudnia 2019 r.)

submodule--helper: porady dotyczące krytycznego błędu alternatywnego

Podpisał: Jonathan Tan
Potwierdził: Jeff King

Podczas rekurencyjnego klonowania superprojektu z niektórymi płytkimi modułami zdefiniowanymi w jego .gitmodules, a następnie ponownego klonowania za pomocą „ --reference=<path>”, pojawia się błąd. Na przykład:

git clone --recurse-submodules --branch=master -j8 \
  https://android.googlesource.com/platform/superproject \
  master
git clone --recurse-submodules --branch=master -j8 \
  https://android.googlesource.com/platform/superproject \
  --reference master master2

zawodzi z:

fatal: submodule '<snip>' cannot add alternate: reference repository
'<snip>' is shallow

Gdy nie można dodać alternatywy obliczonej na podstawie alternatywy superprojektu, czy to w tym czy innym przypadku, radzimy submodule.alternateErrorStrategyskonfigurować opcję konfiguracyjną " " i używać " --reference-if-able" zamiast " --reference" podczas klonowania.

Jest to szczegółowo opisane w:

W Git 2.25 (Q1 2020) interakcja między "git clone --recurse-submodules" a alternatywnym magazynem obiektów była źle zaprojektowana.

Doc: wyjaśnij submodule.alternateErrorStrategy

Podpisał: Jonathan Tan
Potwierdził: Jeff King

Commit 31224cbdc7 (" clone: opcja rekurencyjna i referencyjna wyzwala alternatywy podmodułu", 2016-08-17, Git v2.11.0-rc0 - scalanie wymienione w partii nr 1 ) nauczyło Git obsługiwać opcje konfiguracyjne " submodule.alternateLocation" i " submodule.alternateErrorStrategy" superprojektu .

Jeśli „ submodule.alternateLocation” jest skonfigurowany na „ superproject” w superprojekcie, za każdym razem, gdy klonowany jest podmoduł tego superprojektu, zamiast tego oblicza analogiczną ścieżkę alternatywną dla tego $GIT_DIR/objects/info/alternatesmodułu podrzędnego z superprojektu i odwołuje się do niego.

Opcja „ submodule.alternateErrorStrategy” określa, co się stanie, jeśli nie można się odwołać do tej alternatywy.
Jednak nie jest jasne, czy klon przebiega tak, jakby nie określono alternatywy, gdy ta opcja nie jest ustawiona na „die” (co widać w testach w 31224cbdc7 ).
Dlatego należy to odpowiednio udokumentować.

Dokumentacja modułu podrzędnego konfiguracji zawiera teraz:

submodule.alternateErrorStrategy::

Określa, jak traktować błędy z zamiennikami dla modułu podrzędnego obliczonymi za pośrednictwem submodule.alternateLocation.
Możliwe są następujące wartości ignore, info, die.
Domyślnie jest die.
Zauważ, że jeśli jest ustawiona na ignorelub infoi jeśli wystąpi błąd w obliczonej alternatywie, klon działa tak, jakby nie określono alternatywy .

VonC
źródło
2
Wow, to było szybkie! Dzięki za odpowiedź. Aha i powinienem też się --depthpokłócić;)
Brice,
3
Wydawałoby mi się, że zatwierdzenie fb43e31 żąda brakującego zatwierdzenia przez identyfikator SHA1, więc ustawienia uploadpack.allowReachableSHA1InWanti uploadpack.allowTipSHA1InWantna serwerze prawdopodobnie wpłyną na to, czy to zadziała. Napisałem dzisiaj post do listy git , wskazując, w jaki sposób użycie płytkich podmodułów może działać lepiej w niektórych scenariuszach, a mianowicie, jeśli zatwierdzenie jest również tagiem. Poczekajmy i zobaczmy.
MvG
2
Po niedawnym dodaniu opcji shallow w .gitmodules, czy ta --depth 1opcja działa dla gałęzi, które nie śledzą dokładnie wzorca?
CMCDragonkai,
2
@CiroSantilli 刘晓波 死 六四 事件 法轮功 Dziękuję za precyzję i test. Załączam Twój komentarz do odpowiedzi, aby była bardziej widoczna, i zagłosowałem za Twoją odpowiedzią.
VonC
2
Z odpowiedzi nie wynika jasno, jaki jest obecny sposób na to. Ponadto nie jest jasne, czy wszystko to jest potrzebne za każdym razem, gdy ktoś klonuje nową kopię lub te skąpe ustawienia podmodułów stają się częścią repozytorium, które odwołuje się do tych podmodułów (np. Każda nowa aktualizacja klonu i podmodułu skutkuje rzadkimi pobraniami modułów podrzędnych)
Pavel P
26

Git 2.9.0 obsługuje podmoduły płytkie klonowanie bezpośrednio, więc teraz możesz po prostu zadzwonić:

git clone url://to/source/repository --recursive --shallow-submodules
KindDragon
źródło
2
Ta opcja jest najbardziej obiecująca, ale zawodzi w git 2.14.1 zatwierdzenie podmodułu nie jest śledzone ani przez gałąź, ani przez tag: stackoverflow.com/a/47374702/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
@CiroSantilli 刘晓波 死 六四 事件 法轮功 Upewnij się, że Twój serwer git jest również zaktualizowany
KindDragon
Dzięki, testowałem lokalnie, bez serwera i na GitHubie, którego nie mogę zaktualizować :-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
Mam ten sam problem przy użyciu git 2.20, nie działa, gdy podmoduł nie znajduje się na końcu gałęzi.
Zitrax
16

Idąc za odpowiedzią Ryana, udało mi się wymyślić ten prosty skrypt, który iteruje przez wszystkie moduły podrzędne i płytko je klonuje:

#!/bin/bash
git submodule init
for i in $(git submodule | sed -e 's/.* //'); do
    spath=$(git config -f .gitmodules --get submodule.$i.path)
    surl=$(git config -f .gitmodules --get submodule.$i.url)
    git clone --depth 1 $surl $spath
done
git submodule update
Mauricio Scheffer
źródło
Dostaję fatal: reference is not a tree: 88fb67b07621dfed054d8d75fd50672fb26349dfza każdy podmoduł
knocte
@knocte czy widziałeś stackoverflow.com/questions/2144406/git-shallow-submodules/…
Mauricio Scheffer
1
@knocte: Napisałem swoją odpowiedź w 2010 roku. Wszystko się zmieniło. Nie możesz oczekiwać, że wszyscy zachowają wszystkie swoje odpowiedzi. Oznaczyłem aktualną prawidłową odpowiedź jako zaakceptowaną.
Mauricio Scheffer
13
@knocte To jeden z powodów, dla których przestałem współtworzyć Stackoverflow. Ludzie mają te nierealistyczne oczekiwania. Utrzymanie każdej z moich 1637 odpowiedzi wymagałoby pracy na pełny etat. A potem są też komentarze, przypuszczam, że musiałbym je również zachować? Spójrz na daty, po to są. Gdybyś czytał jakiś blog .NET z 2002 roku z kodem używającym ArrayList zamiast List, czy użyłbyś tego? Czy chciałbyś, aby autor zaktualizował swój post? Ta sama zasada obowiązuje tutaj.
Mauricio Scheffer
1
s / statusquo / progress /
knocte
8

Czytając git-submodule „source”, wygląda na to, że git submodule addmoże obsłużyć moduły podrzędne, które mają już swoje repozytoria. W tym wypadku...

$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
$ git submodule add $remotesub1 $sub1
#repeat as necessary...

Będziesz chciał się upewnić, że wymagane zatwierdzenie znajduje się w repozytorium modułu podrzędnego, więc upewnij się, że ustawiłeś odpowiednią --depth.

Edycja: Możesz być w stanie uciec z wieloma ręcznymi klonami podmodułów, a następnie jedną aktualizacją:

$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
#repeat as necessary...
$ git submodule update
Ryan Graham
źródło
5
Teraz dla git 1.8.0 nie możesz już klonować repozytorium wewnątrz repozytorium. Więc to rozwiązanie już nie działa.
Bohr
7

Podsumowanie błędnego / nieoczekiwanego / denerwującego zachowania od Git 2.14.1

  1. shallow = truew .gitmodulestylko wpływa git clone --recurse-submodulesjeżeli HEADz odległych punktów modułem do wymaganej popełnić, nawet jeśli cel popełnić jest wskazywany przez oddział, a nawet jeśli umieścić branch = mybranchna .gitmodulesjak dobrze.

    Lokalny skrypt testowy . To samo zachowanie na GitHub 2017-11, gdzie HEADjest kontrolowane przez domyślne ustawienie repozytorium gałęzi:

    git clone --recurse-submodules https://github.com/cirosantilli/test-shallow-submodule-top-branch-shallow
    cd test-shallow-submodule-top-branch-shallow/mod
    git log
    # Multiple commits, not shallow.
    
  2. git clone --recurse-submodules --shallow-submodulesnie powiedzie się, jeśli nie jest ani zobowiązać się odwoływać przez oddział lub tagu z komunikatem: error: Server does not allow request for unadvertised object.

    Lokalny skrypt testowy . To samo zachowanie na GitHub:

    git clone --recurse-submodules --shallow-submodules https://github.com/cirosantilli/test-shallow-submodule-top-sha
    # error
    

    Zapytałem również na liście mailingowej: https://marc.info/?l=git&m=151863590026582&w=2 i odpowiedź brzmiała:

    W teorii powinno to być łatwe. :)

    W praktyce niestety niewiele. Dzieje się tak, ponieważ klonowanie pozwala uzyskać najnowszą końcówkę gałęzi (zwykle master). W klonie nie ma mechanizmu, który pozwoliłby dokładnie określić żądany sha1.

    Protokół Wire obsługuje zadawanie dokładnych wartości sha1, więc powinno to być uwzględnione. (Uwaga: działa tylko wtedy, gdy operator serwera włączy uploadpack.allowReachableSHA1InWant, który github nie ma AFAICT)

    git-fetch pozwala na pobranie dowolnego sha1, więc jako obejście można uruchomić pobieranie po klonie rekurencyjnym, używając opcji „git submodule update”, ponieważ po pierwszym klonie będzie używane pobieranie.

Test TODO: allowReachableSHA1InWant.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
źródło
Wygląda na to, że po prostu nie ma prostego sposobu na sprawdzenie odłączonego skrótu zatwierdzenia HEAD dla podmodułu i otrzymanie dalszych użytkowników, git clone --recursivektórzy pobierają tylko to konkretne zatwierdzenie.
CMCDragonkai
3

Czy kanoniczne lokalizacje modułów podrzędnych są zdalne? Jeśli tak, czy możesz je raz sklonować? Innymi słowy, czy chcesz mieć płytkie klony tylko dlatego, że cierpisz z powodu zmarnowanej przepustowości częstych (re) klonów submodułów?

Jeśli chcesz, aby płytkie klony oszczędzały lokalną przestrzeń dyskową, odpowiedź Ryana Grahama wydaje się być dobrym rozwiązaniem. Ręcznie sklonuj repozytoria, aby były płytkie. Jeśli uważasz, że byłoby to przydatne, dostosuj się, git submoduleaby je wspierać. Wyślij e-mail do listy z pytaniem o to (porady dotyczące implementacji, sugestie dotyczące interfejsu itp.). Moim zdaniem ludzie bardzo wspierają potencjalnych współpracowników, którzy szczerze chcą ulepszyć Git w konstruktywny sposób.

Jeśli nie przeszkadza ci wykonanie jednego pełnego klonu każdego modułu podrzędnego (plus późniejsze pobieranie, aby były aktualne), możesz spróbować użyć --referenceopcji git submodule update(jest w Git 1.6.4 i nowszych), aby odwołać się do lokalnych magazynów obiektów (np. utwórz --mirrorklony kanonicznych repozytoriów podmodułów, a następnie użyj --referencew swoich modułach podrzędnych, aby wskazać te lokalne klony). Pamiętaj, aby przeczytać o git clone --reference/ git clone --sharedprzed użyciem --reference. Jedynym prawdopodobnym problemem z odwoływaniem się do serwerów lustrzanych byłoby to, że kiedykolwiek pobierałyby aktualizacje bez szybkiego przewijania do przodu (chociaż można włączyć reflogs i rozszerzyć ich okna wygaśnięcia, aby pomóc zachować wszelkie porzucone zatwierdzenia, które mogą powodować problem). Dopóki nie powinieneś mieć żadnych problemów

  • nie wykonujesz żadnych zatwierdzeń lokalnych modułów podrzędnych lub
  • wszelkie zatwierdzenia, które są zawieszone przez nie szybkie przekazywanie, które repozytoria kanoniczne mogą publikować, nie są przodkami w stosunku do zatwierdzeń lokalnego modułu podrzędnego, lub
  • dokładasz starań, aby w repozytoriach modułów podrzędnych kanonicznych ponownie opierać zatwierdzenia lokalnego modułu podrzędnego, niezależnie od tego, co nie jest szybkie przekazywanie do przodu.

Jeśli zdecydujesz się na coś takiego i jest jakakolwiek szansa, że ​​możesz przenosić lokalne zatwierdzenia podmodułów w swoich drzewach roboczych, prawdopodobnie dobrym pomysłem byłoby utworzenie zautomatyzowanego systemu, który upewni się, że krytyczne obiekty, do których odwołują się wyewidencjonowane podmoduły, nie są pozostawione wiszące w repozytoriach lustrzanych (a jeśli jakieś zostaną znalezione, kopiuje je do repozytoriów, które ich potrzebują).

I, jak git clonemówi strona podręcznika, nie używaj, --referencejeśli nie rozumiesz tych konsekwencji.

# Full clone (mirror), done once.
git clone --mirror $sub1_url $path_to_mirrors/$sub1_name.git
git clone --mirror $sub2_url $path_to_mirrors/$sub2_name.git

# Reference the full clones any time you initialize a submodule
git clone $super_url super
cd super
git submodule update --init --reference $path_to_mirrors/$sub1_name.git $sub1_path_in_super
git submodule update --init --reference $path_to_mirrors/$sub2_name.git $sub2_path_in_super

# To avoid extra packs in each of the superprojects' submodules,
#   update the mirror clones before any pull/merge in super-projects.
for p in $path_to_mirrors/*.git; do GIT_DIR="$p" git fetch; done

cd super
git pull             # merges in new versions of submodules
git submodule update # update sub refs, checkout new versions,
                     #   but no download since they reference the updated mirrors

Alternatywnie, zamiast tego --reference, możesz użyć klonów lustrzanych w połączeniu z domyślną funkcją łączenia twardego git clone, używając lokalnych serwerów lustrzanych jako źródła dla swoich podmodułów. W nowych klonach superprojektów git submodule initedytuj adresy URL podmodułów, .git/configaby wskazywały na lokalne serwery lustrzane, a następnie wykonajgit submodule update. Aby uzyskać dowiązania twarde, musisz ponownie klonować wszystkie istniejące wyewidencjonowane moduły podrzędne. Możesz zaoszczędzić przepustowość, pobierając tylko raz do serwerów lustrzanych, a następnie pobierając lokalnie z tych do wyewidencjonowanych podmodułów. Twarde łączenie pozwoliłoby zaoszczędzić miejsce na dysku (chociaż pobrania miałyby tendencję do gromadzenia się i duplikowania w wielu instancjach składnic obiektów wyewidencjonowanych podmodułów; można okresowo ponownie klonować wyewidencjonowane podmoduły z serwerów lustrzanych, aby odzyskać oszczędność miejsca na dysku zapewnianą przez łączenie twarde).

Chris Johnsen
źródło
2

Stworzyłem nieco inną wersję, gdy nie działa na krawędzi, co nie we wszystkich projektach. Standardowe dodatki do submodułów nie działały, podobnie jak powyższy skrypt. Więc dodałem wyszukiwanie skrótu dla ref tagu, a jeśli go nie ma, wraca do pełnego klonu.

#!/bin/bash
git submodule init
git submodule | while read hash name junk; do
    spath=$(git config -f .gitmodules --get submodule.$name.path)
    surl=$(git config -f .gitmodules --get submodule.$name.url)
    sbr=$(git ls-remote --tags $surl | sed -r "/${hash:1}/ s|^.*tags/([^^]+).*\$|\1|p;d")
    if [ -z $sbr ]; then
        git clone $surl $spath
    else
        git clone -b $sbr --depth 1 --single-branch $surl $spath
    fi
done
git submodule update 
sfossen
źródło
2

Odniesienie do Jak sklonować repozytorium git z określoną wersją / zestawem zmian?

Napisałem prosty skrypt, który nie ma problemu, gdy odniesienie do modułu podrzędnego jest oddalone od wzorca

git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch origin {} && git reset --hard FETCH_HEAD'

Ta instrukcja pobierze wskazaną wersję modułu podrzędnego.

Jest szybki, ale nie możesz zatwierdzić swojej edycji w module podrzędnym (musisz go pobrać przed https://stackoverflow.com/a/17937889/3156509 )

w pełni:

#!/bin/bash
git submodule init
git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch origin {} && git reset --hard FETCH_HEAD'
git submodule update --recursive
Beeno Tung
źródło
1

Płytkie klony podmodułu są idealne, ponieważ wykonują migawki w określonej wersji / zestawie zmian. Pobranie pliku ZIP ze strony internetowej jest łatwe, więc próbowałem znaleźć skrypt.

#!/bin/bash
git submodule deinit --all -f
for value in $(git submodule | perl -pe 's/.*(\w{40})\s([^\s]+).*/\1:\2/'); do
  mysha=${value%:*}
  mysub=${value#*:}
  myurl=$(grep -A2 -Pi "path = $mysub" .gitmodules | grep -Pio '(?<=url =).*/[^.]+')
  mydir=$(dirname $mysub)
  wget $myurl/archive/$mysha.zip
  unzip $mysha.zip -d $mydir
  test -d $mysub && rm -rf $mysub
  mv $mydir/*-$mysha $mysub
  rm $mysha.zip
done
git submodule init

git submodule deinit --all -f czyści drzewo podmodułów, co umożliwia wielokrotne użycie skryptu.

git submodulepobiera 40 znaków sha1, po których następuje ścieżka odpowiadająca temu samemu plikowi .gitmodules. Używam perla do łączenia tych informacji, oddzielonych dwukropkiem, a następnie używam transformacji zmiennej, aby rozdzielić wartości na myshai mysub.

Są to klucze krytyczne, ponieważ potrzebujemy sha1 do pobrania i ścieżki do skorelowania urlw .gitmodules.

Biorąc pod uwagę typowy wpis podmodułu:

[submodule "label"]
    path = localpath
    url = https://github.com/repository.git

myurlklawisze path =następnie patrzy 2 wiersze dalej, aby uzyskać wartość. Ta metoda może nie działać konsekwentnie i wymagać udoskonalenia. Url grep usuwa wszelkie pozostałe .gitodwołania do typów, dopasowując je do ostatniego /i wszystkiego do a ..

mydirjest mysubminusem końcowym, /namektóry oznaczałby katalog prowadzący do nazwy modułu podrzędnego.

Dalej jest wgetw formacie adresu URL archiwum zip do pobrania. Może się to zmienić w przyszłości.

Rozpakuj plik, do mydirktórego byłby podkatalog określony w ścieżce podmodułu. Wynikowy folder będzie ostatnim elementem url- sha1.

Sprawdź, czy podkatalog określony w ścieżce modułu podrzędnego istnieje i usuń go, aby umożliwić zmianę nazwy wyodrębnionego folderu.

mv zmień nazwę wyodrębnionego folderu zawierającego nasz sha1 na prawidłową ścieżkę do modułu podrzędnego.

Usuń pobrany plik zip.

Inicjalizacja modułu podrzędnego

Jest to bardziej dowód słuszności WIP niż rozwiązanie. Kiedy to działa, wynikiem jest płytki klon podmodułu przy określonym zestawie zmian.

Jeśli repozytorium przywróci moduł podrzędny do innego zatwierdzenia, uruchom ponownie skrypt w celu aktualizacji.

Jedyny przypadek, w którym taki skrypt byłby przydatny, jest przydatny w przypadku lokalnego tworzenia projektu źródłowego bez współpracy.

noabody
źródło