Mam projekt z submodułem Git. Pochodzi z adresu URL ssh: // ... i jest na zatwierdzeniu A. Commit B został wypchnięty na ten adres URL i chcę, aby podmoduł odzyskał zatwierdzenie i zmienił go.
Teraz rozumiem, że git submodule update
powinno to zrobić, ale tak nie jest. Nic nie robi (brak danych wyjściowych, kod zakończenia sukcesu). Oto przykład:
$ mkdir foo
$ cd foo
$ git init .
Initialized empty Git repository in /.../foo/.git/
$ git submodule add ssh://user@host/git/mod mod
Cloning into mod...
user@host's password: hunter2
remote: Counting objects: 131, done.
remote: Compressing objects: 100% (115/115), done.
remote: Total 131 (delta 54), reused 0 (delta 0)
Receiving objects: 100% (131/131), 16.16 KiB, done.
Resolving deltas: 100% (54/54), done.
$ git commit -m "Hello world."
[master (root-commit) 565b235] Hello world.
2 files changed, 4 insertions(+), 0 deletions(-)
create mode 100644 .gitmodules
create mode 160000 mod
# At this point, ssh://user@host/git/mod changes; submodule needs to change too.
$ git submodule init
Submodule 'mod' (ssh://user@host/git/mod) registered for path 'mod'
$ git submodule update
$ git submodule sync
Synchronizing submodule url for 'mod'
$ git submodule update
$ man git-submodule
$ git submodule update --rebase
$ git submodule update
$ echo $?
0
$ git status
# On branch master
nothing to commit (working directory clean)
$ git submodule update mod
$ ...
Próbowałem zostały również git fetch mod
, co wydaje się zrobić fetch (ale może nie być może, bo to nie monitowania o hasło!), Ale git log
i git show
zaprzeczyć istnieniu nowych zatwierdzeń. Do tej pory właśnie rm
modyfikowałem moduł i dodawałem go ponownie, ale jest to zarówno złe w zasadzie, jak i żmudne w praktyce.
git
git-submodules
git-pull
Tanatos
źródło
źródło
--remote
opcji, być może warto byłoby zaznaczyć to jako odpowiedź zaakceptowaną, a nie podejście „ręczne” w odpowiedzi Jasona?--remote
jest zdecydowanie lepszym rozwiązaniem w tym momencie, a ponieważ pytanie to zostało powiązane z Github Gist na temat submodułów, uważam, że lepiej byłoby, aby przybywający czytelnicy zobaczyli nową odpowiedź.hunter2
hasłem: o)Odpowiedzi:
git submodule update
Komenda faktycznie mówi Git, że chcesz, aby submodules każdemu Sprawdź commit już określone w indeksie superproject. Jeśli chcesz zaktualizować swoje submoduły do najnowszego zatwierdzenia dostępnego z ich pilota, musisz to zrobić bezpośrednio w submodułach.Podsumowując:
Lub, jeśli jesteś zajęty:
źródło
git submodule foreach git pull
git submodule foreach git pull origin master
.git submodule foreach --recursive git pull origin master
.-a
Przełącznik opcjigit commit
„Powiedz [s] komendzie, aby automatycznie dostosowywał pliki, które zostały zmodyfikowane i usunięte, ale nie dotyczy to nowych plików, o których nie powiedziałeś Gitowi”.Git 1.8.2 oferuje nową opcję
--remote
, która umożliwi dokładnie takie zachowanie. Bieganiepobierze najnowsze zmiany z wyższego poziomu w każdym podmodule, scali je i sprawdzi najnowszą wersję tego podmodułu. Jak to dokumentuje :
Jest to równoważne z uruchomieniem
git pull
w każdym podmodule, co jest generalnie dokładnie tym, czego chcesz.źródło
git pull
w każdym podmodule”. Aby wyjaśnić, nie ma różnicy (z perspektywy użytkownika) między odpowiedzią agit submodule foreach git pull
?foreach git pull
tylko je sprawdziłem, ale nie zaktualizowałem wskaźnika głównego repozytorium, aby wskazywał na nowsze zatwierdzenie submodułu. Tylko dzięki--remote
niemu wskazywał na ostatnie zatwierdzenie.W katalogu nadrzędnym projektu uruchom:
Lub jeśli masz rekurencyjne uruchamianie submodułów:
Czasami to nadal nie działa, ponieważ jakoś masz lokalne zmiany w lokalnym katalogu podmodułu podczas aktualizacji tego podmodułu.
Przez większość czasu zmiana lokalna może nie być tą, którą chcesz zatwierdzić. Może się to zdarzyć z powodu usunięcia pliku w podmodule itp. Jeśli tak, wykonaj reset w lokalnym katalogu podmodułów i katalogu nadrzędnym projektu, uruchom ponownie:
źródło
Twój główny projekt wskazuje na konkretne zatwierdzenie, w którym powinien być podmoduł.
git submodule update
próbuje sprawdzić zatwierdzenie w każdym zainicjowanym podmodule. Podmoduł jest tak naprawdę niezależnym repozytorium - po prostu utworzenie nowego zatwierdzenia w podmodule i wypychanie to nie wystarczy. Musisz także wyraźnie dodać nową wersję submodułu w głównym projekcie.Tak więc w twoim przypadku powinieneś znaleźć właściwe zatwierdzenie w submodule - załóżmy, że to jest wskazówka
master
:Teraz wróć do głównego projektu, przygotuj podmoduł i potwierdź, że:
Teraz wypuść nową wersję głównego projektu:
Od tego momentu, jeśli ktokolwiek inny zaktualizuje swój główny projekt, to
git submodule update
dla niego zaktualizuje submoduł, zakładając, że został zainicjowany.źródło
Wygląda na to, że w tej dyskusji łączone są dwa różne scenariusze:
Scenariusz 1
Używając wskaźników mojego repozytorium nadrzędnego do podmodułów, chcę sprawdzić zatwierdzenie w każdym podmodule, na który wskazuje repozytorium nadrzędne, być może po pierwszej iteracji przez wszystkie podmoduły i aktualizacji / ściągnięciu ich ze zdalnego.
Jest to, jak wskazano, zrobione z
Scenariusz 2, do którego, jak sądzę, dąży
W jednym lub więcej submodułach wydarzyły się nowe rzeczy i chcę 1) pobrać te zmiany i 2) zaktualizować repozytorium nadrzędne, aby wskazywało zatwierdzenie HEAD (najnowsze) tego / tych submodułów.
Zostanie to zrobione przez
Niezbyt praktyczne, ponieważ musiałbyś zakodować n ścieżek do wszystkich n podmodułów, np. W skrypcie, aby zaktualizować wskaźniki zatwierdzenia repozytorium nadrzędnego.
Byłoby fajnie mieć zautomatyzowaną iterację przez każdy podmoduł, aktualizując wskaźnik nadrzędnego repozytorium (za pomocą
git add
), aby wskazywał na głowę submodułu (-ów).W tym celu stworzyłem ten mały skrypt Bash:
git-update-submodules.sh
Aby go uruchomić, uruchom
Opracowanie
Po pierwsze zakładam, że gałąź o nazwie $ BRANCH (drugi argument) istnieje we wszystkich repozytoriach. Możesz to jeszcze bardziej skomplikować.
Pierwsza para sekcji to sprawdzanie, czy istnieją argumenty. Następnie ściągam najnowsze rzeczy z repozytorium nadrzędnego (wolę używać --ff (szybkie przewijanie do przodu) za każdym razem, gdy robię ciągnięcia. Mam wyłączoną bazę, BTW).
W takim przypadku może być konieczne zainicjowanie niektórych modułów podrzędnych, jeśli dodano nowe moduły podrzędne lub nie zostały jeszcze zainicjowane:
Następnie aktualizuję / ściągam wszystkie podmoduły:
Zwróć uwagę na kilka rzeczy: Po pierwsze, łączę niektóre polecenia Git za pomocą
&&
- co oznacza, że poprzednie polecenie musi zostać wykonane bezbłędnie.Po możliwym udanym pobraniu (jeśli nowe rzeczy zostały znalezione na pilocie), robię push, aby upewnić się, że ewentualne scalenie-zatwierdzenie nie zostanie pozostawione na kliencie. Znowu dzieje się tak tylko wtedy, gdy pociągnięcie rzeczywiście przynosi nowe rzeczy.
Wreszcie, ostatecznym
|| true
zadaniem jest upewnienie się, że skrypt kontynuuje błędy. Aby to zadziałało, wszystko w iteracji musi być zawinięte w cudzysłowy, a polecenia Git są umieszczone w nawiasach (pierwszeństwo operatora).Moja ulubiona część:
Iteruj wszystkie podmoduły - za pomocą
--quiet
, która usuwa wyjście „Wprowadzanie MODULE_PATH”. Używając'echo $path'
(musi być w cudzysłowach), ścieżka do submodułu zostaje zapisana do wyjścia.Ta lista względnych ścieżek podmodułu jest przechwytywana w array (
$(...)
) - w końcu iteruj to i zróbgit add $i
aktualizację repozytorium nadrzędnego.Na koniec zatwierdzenie z komunikatem wyjaśniającym, że repozytorium nadrzędne zostało zaktualizowane. To zatwierdzenie zostanie domyślnie zignorowane, jeśli nic nie zostało zrobione. Wciśnij to do źródła i gotowe.
Mam skrypt uruchamiający to w zadaniu Jenkins, który następnie łączy się z zaplanowanym automatycznym wdrożeniem i działa jak urok.
Mam nadzieję, że komuś to pomoże.
źródło
pwd
Polecenie drukuje właściwe „absolutną ścieżkę” dla każdego występującego submodule;--recursive
zapewnia, że odwiedzamy wszystkie submoduły, w tym submoduły-w ramach submodułów -..., które mogą być obecne w dużym projekcie. Obie metody powodują problemy z katalogami zawierającymi spacje, np./c/Users/Ger/Project\ Files/...
Dlatego zasadą jest, aby nigdy nie używać białych znaków nigdzie w naszych projektach.--remote
opcję.git submodule update --remote
zachowuje się mniej więcej tak jak skrypt.The remote branch used defaults to master, but the branch name may be overridden by setting the submodule.<name>.branch option in either .gitmodules or .git/config (with .git/config taking precedence).
Nie chcę edytować .gitmodules ani .git / config za każdym razem, gdy chcę to zrobić w innej gałęzi niż master. Ale może coś przeoczyłem? Ponadto metoda wydaje się wymuszać połączenia rekurencyjne (tym samym nie ma możliwości szybkiego przewijania do przodu).Prosty i prosty, aby pobrać submoduły:
A teraz kontynuuj aktualizację do najnowszej gałęzi głównej (na przykład):
źródło
Uwaga, podczas gdy nowoczesną formą aktualizacji zatwierdzeń submodułu byłyby:
Starsza forma to:
Z wyjątkiem ... ta druga forma nie jest tak naprawdę „cicha”.
Zobacz commit a282f5a (12 kwietnia 2019) autor: Nguyễn Thái Ngọc Duy (
pclouds
) .(Połączone przez Junio C Hamano -
gitster
- w commit f1c9f6c , 25 kwietnia 2019)A Git 2.23 (III kwartał 2019 r.) Rozwiązuje inny problem: „
git submodule foreach
” nie chronił opcji wiersza poleceń przekazanych do polecenia, które ma być poprawnie uruchomione w każdym podmodule, gdy--recursive
była używana opcja „ ”.Zobacz zatwierdzenie 30db18b (24 czerwca 2019 r.) Przez Morian Sonnet (
momoson
) .(Połączone przez Junio C Hamano -
gitster
- w commit 968eecb , 09 lipca 2019)źródło
Spowoduje to ściągnięcie wszystkich najnowszych zatwierdzeń.
źródło
W moim przypadku chciałem
git
zaktualizować do najnowszej wersji i jednocześnie uzupełnić brakujące pliki.Następujące pliki przywróciły brakujące pliki (dzięki
--force
czemu nie wydaje się tutaj wspomniane), ale nie pobrały żadnych nowych zatwierdzeń:git submodule update --init --recursive --force
To spowodowało:
git submodule update --recursive --remote --merge --force
źródło
@Jason ma rację, ale nie do końca.
Tak
git submodule update
samo robi kasy, ale dotyczy zatwierdzenia w indeksie zawierającego repozytorium. W ogóle jeszcze nie wie o nowym zatwierdzeniu na wcześniejszym etapie. Więc przejdź do swojego podmodułu, pobierz żądane zatwierdzenie i zatwierdź zaktualizowany stan podmodułu w głównym repozytorium, a następnie wykonajgit submodule update
.źródło
git submodule update
, aktualizacja przeniesie podmoduł do zatwierdzenia określonego w bieżącej HEAD superprojektu. (cokolwiek ostatnie zatwierdzenie w superprojekcie mówi, że podprojekt powinien być - takie zachowanie, po wyjaśnieniu w poście Jasona, wydaje mi się logiczne) Wydaje się również, że jest pobierane, ale tylko w przypadku, gdy podprojekt ma niewłaściwe zatwierdzenie , co dodawało mi zamieszania.Oto niesamowity one-liner do aktualizacji wszystkiego do najnowszej wersji master:
Dzięki Mark Jaquith
źródło
Jeśli nie znasz gałęzi hosta, zrób to:
Otrzyma gałąź głównego repozytorium Git, a następnie dla każdego podmodułu wykona tę samą gałąź.
źródło
Jeśli chcesz
master
pobrać gałąź dla każdego podmodułu - możesz w tym celu użyć następującego polecenia:źródło