Zaktualizuj Git submodule do najnowszego commita na origin
Mam projekt z podmodułem Git. Jest z ssh://... URL, i jest na commit A. Commit B został wypchnięty na ten adres URL i chcę, aby podmoduł odzyskał commit i zmienił na niego.
Rozumiem, że git submodule update
powinno to zrobić, ale tak nie jest. nic nie robi (brak wyjścia, kod wyjścia 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 również git fetch mod
, który wydaje się robić aport (ale nie może, bo to nie monituje o hasło!), ale git log
i git show
zaprzeczają istnieniu nowych commitów. Do tej pory po prostu[5]}-ing moduł i ponowne dodanie go, ale jest to zarówno złe w zasadzie i żmudne w praktyce.
9 answers
The git submodule update
polecenie mówi Gitowi, że chcesz, aby każdy z Twoich podmodułów sprawdzał commit już określony w indeksie superprojekt. Jeśli chcesz zaktualizować swoje podmoduły do najnowszego commita dostępnego z ich pilota, musisz to zrobić bezpośrednio w podmodułach.
Tak w podsumowaniu:
# get the submodule initially
git submodule add ssh://bla submodule_dir
git submodule init
# time passes, submodule upstream is updated
# and you now want to update
# change to the submodule directory
cd submodule_dir
# checkout desired branch
git checkout master
# update
git pull
# get back to your project root
cd ..
# now the submodules are in the state you want, so
git commit -am "Pulled down update to submodule_dir"
Lub, jeśli jesteś zajętą osobą:
git submodule foreach git pull origin master
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-01 18:36:57
Git 1.8.2 zawiera nową opcję --remote
, która umożliwi dokładnie takie zachowanie. Running
git submodule update --remote --merge
Pobierze najnowsze zmiany z podmodułu, połączy je i sprawdzi najnowszą wersję podmodułu. Jak to ujął docs :
--remote
Ta opcja jest ważna tylko dla polecenia update. Zamiast używać nagranego SHA-1 superprojektu do aktualizacji podmodułu, użyj statusu zdalnego śledzenia podmodułu branch.
Jest to równoznaczne z uruchomieniem git pull
w każdym podmodule, co generalnie jest dokładnie tym, czego chcesz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-01 18:36:05
W katalogu nadrzędnym projektu Uruchom:
git submodule update --init
Lub jeśli masz rekurencyjne podmoduły Uruchom:
git submodule update --init --recursive
Czasami to nadal nie działa, ponieważ w jakiś sposób masz lokalne zmiany w lokalnym katalogu submodule, podczas gdy submodule jest aktualizowany.
Przez większość czasu lokalna zmiana może nie być tą, którą chcesz wprowadzić. Może się to zdarzyć z powodu usunięcia pliku w podmodule itp. Jeśli tak, wykonaj reset w lokalnym katalogu podmoduł i w rodzicu projektu katalog uruchom ponownie:
git submodule update --init --recursive
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-18 08:25:40
Twój główny projekt wskazuje na konkretny commit, w którym powinien znajdować się podmoduł. git submodule update
robi to, aby sprawdzić ten commit w każdym podmodule, który został zainicjowany. Submodule jest tak naprawdę niezależnym repozytorium - samo stworzenie nowego commita w submodule i wciskanie tego nie wystarczy, musisz również wyraźnie dodać nową wersję submodule w głównym projekcie.
Więc w Twoim przypadku powinieneś znaleźć odpowiedni commit w podmodule-Załóżmy, że "końcówka mistrza": {]}
cd mod
git checkout master
git pull origin master
Teraz wróć do głównego projektu, ustaw podmoduł i zatwierdź:
cd ..
git add mod
git commit -m "Updating the submodule 'mod' to the latest version"
Teraz wypchnij nową wersję głównego projektu:
git push origin master
Od tego momentu, Jeśli ktoś inny zaktualizuje swój główny projekt, to git submodule update
dla niego zaktualizuje podmoduł, zakładając, że został zainicjowany.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-29 06:12:17
Wygląda na to, że w tej dyskusji mieszają się dwa różne scenariusze:
Scenariusz 1
Używając wskaźników mojego rodzica repo do podmodułów, chcę sprawdzić commit w każdym podmodule, na który wskazuje rodzic repo, prawdopodobnie po pierwszej iteracji przez wszystkie podmoduły i aktualizacji / ściągnięciu ich z pilota.
Jest to, jak zaznaczono, zrobione
git submodule foreach git pull origin BRANCH
git submodule update
Scenariusz 2, który moim zdaniem jest celem OP at
Nowe rzeczy wydarzyły się w 1 lub więcej podmodułach i chcę 1) wyciągnąć te zmiany i 2) zaktualizować repo rodzica, aby wskazać HEAD (latest) commit tego/tych podmodułów.
To będzie zrobione przez
git submodule foreach git pull origin BRANCH
git add module_1_name
git add module_2_name
......
git add module_n_name
git push origin BRANCH
Nie jest to zbyt praktyczne, ponieważ trzeba by kodować na twardo n ścieżek do wszystkich N podmoduł, np. w skrypcie, aby zaktualizować wskaźniki zatwierdzania repo.
Co byłoby fajne dla automatycznej iteracji za pośrednictwem każdego podmodułu, aktualizowanie nadrzędny wskaźnik repo (używając git add) wskazuje na główkę podmodułu (- ów).
W tym celu zrobiłem mały skrypt bash:
git-update-submodules.sh
#!/bin/bash
APP_PATH=$1
shift
if [ -z $APP_PATH ]; then
echo "Missing 1st argument: should be path to folder of a git repo";
exit 1;
fi
BRANCH=$1
shift
if [ -z $BRANCH ]; then
echo "Missing 2nd argument (branch name)";
exit 1;
fi
echo "Working in: $APP_PATH"
cd $APP_PATH
git checkout $BRANCH && git pull --ff origin $BRANCH
git submodule sync
git submodule init
git submodule update
git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"
for i in $(git submodule foreach --quiet 'echo $path')
do
echo "Adding $i to root repo"
git add "$i"
done
git commit -m "Updated $BRANCH branch of deployment repo to point to latest head of submodules"
git push origin $BRANCH
Aby go uruchomić, wykonaj
git-update-submodules.sh /path/to/base/repo BRANCH_NAME
Opracowanie
Po pierwsze, zakładam, że gałąź o nazwie $BRANCH (2nd argument) istnieje na wszystkich repo.
Pierwsza para odcinków to jakieś sprawdzenie, czy są argumenty. Następnie wyciągam najnowsze rzeczy repo rodzica (wolę użyć --ff (fast-forwarding), gdy tylko robię ściągi. Mam rebase off, btw).
git checkout $BRANCH && git pull --ff origin $BRANCH
Wtedy może być konieczna inicjalizacja podmoduł, jeśli nowe podmoduły zostały dodane lub nie są jeszcze inicjalizowane:
git submodule sync
git submodule init
git submodule update
Następnie aktualizuję / ściągam wszystkie podmoduły:
git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"
Zwróć uwagę na kilka rzeczy: po pierwsze, łączę kilka komend git za pomocą &&
- co oznacza, że poprzednie polecenie musi być wykonane bez błąd.
Po ewentualnym pomyślnym ściągnięciu (jeśli nowe rzeczy zostały znalezione na pilocie), wykonuję push, aby upewnić się, że ewentualne merge-commit nie zostanie pozostawione na kliencie. Znowu, zdarza się tylko jeśli przyciąganie rzeczywiście przyniosło nowe rzeczy.
Ostatecznie, || true
jest zapewnienie, że skrypt nadal na błędy. Aby to zadziałało, wszystko w iteracji musi być zawinięte w podwójne cudzysłowy, a polecenia git-owinięte w parantezy (operator pierwszeństwo).
Moja ulubiona część:
for i in $(git submodule foreach --quiet 'echo $path')
do
echo "Adding $i to root repo"
git add "$i"
done
Iteracja wszystkich podmoduł-za pomocą --quiet
, która usuwa wyjście 'Wprowadzanie MODULE_PATH'. Używając 'echo $path'
(musi być w cudzysłowach), ścieżka do podmodułu zostanie zapisana do wyjścia.
Ta lista względnych ścieżek podrzędnych jest przechwytywana w tablicy ($(...)
) - na koniec iteratuj to i wykonaj git add $i
, aby zaktualizować repo nadrzędne.
Na koniec commit z jakimś Komunikatem wyjaśniającym, że repo rodzica zostało zaktualizowane. Ten commit będzie domyślnie ignorowany, jeśli nic nie zostało zrobione. Popchnij to do źródła i gotowe.
Mam skrypt uruchamiający to w jenkins-job, który łączy się z zaplanowanym automatycznym wdrożeniem i działa jak urok.
Mam nadzieję, że to komuś pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-15 09:24:42
Proste i proste, aby pobrać podmoduły:
git submodule update --init --recursive
A teraz kontynuuj aktualizację ich do najnowszej gałęzi master (na przykład):
git submodule foreach git pull origin master
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-17 20:48:04
@Jason ma rację w pewnym sensie, ale nie do końca.
Update
Zaktualizuj zarejestrowane moduły podrzędne, tj. klonowanie brakujących podmodułów i sprawdź commit określony w indeks repozytorium zawierającego. Dzięki temu Głowica podmodułowa będzie odłączony, chyba że --rebase lub --merge jest określony lub klucz submodule.$name.update jest ustawiony na rebase lub merge.
Więc, git submodule update robi checkout, ale rzecz w tym, że jest to commit w indeks repozytorium zawierającego. Nie wie jeszcze o nowym commicie w ogóle. Więc idź do swojego podmodułu, Pobierz commit, który chcesz i zatwierdź zaktualizowany stan podmodułu w głównym repo, a następnie wykonaj git submodule update
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-29 06:18:00
Oto niesamowita jedna linijka, która zaktualizuje wszystko do najnowszej wersji master:
git submodule foreach 'git fetch origin --tags; git checkout master; git pull' && git pull && git submodule update --init --recursive
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-28 04:29:02
W moim przypadku chciałem zaktualizować git
do najnowszej i jednocześnie uzupełnić brakujące pliki.
Poniższy plik przywrócił brakujące pliki (dzięki --force
, o którym tu nie wspomniano), ale nie ściągnął żadnych nowych commitów:
git submodule update --init --recursive --force
To:
git submodule update --recursive --remote --merge --force
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-26 05:24:53